久しぶりに PHP でハマったこと - 配列とリファレンス

結構あるあるだと思うのですが、すっかり忘れていてハマってしまいました。 ちなみに PHP のバージョンは 5.5.9 です。

PHP の配列の代入は値渡しです。

$a = [1, 2, 3];

$b = $a[0];

$c = $a;
$c[0] = 4;

print_r($a);
// Array ( [0] => 1 [1] => 2 [2] => 3 )

上記のように代入先の配列 $c の要素を変更しても 元の配列 $a の要素は変更されません。

ところが、次のように 配列の要素を参照渡ししてしまうと その要素はリファレンスになってしまいます。

$a = [1, 2, 3];

$b =& $a[0];

$c = $a;
$c[0] = 4;
$c[1] = 6;

print_r($a);
// Array ( [0] => 4 [1] => 2 [2] => 3 )

その結果、上記のように値渡ししたはずの配列 $c の要素を変更したのに 元の配列 $a の要素が変更されてしまいます。

このとき、更に怖いのが $a の 2つ目の要素は 変更されていないことです。 変数 $b に参照渡しした 1つ目の要素だけがリファレンスになります。

これは関数に引数として配列を渡すときも同じです。

function test($arr) {
    $arr[0] = 8;
}

$a = [1, 2, 3];

$b =& $a[0];

test($a);

print_r($a);
// Array ( [0] => 8 [1] => 2 [2] => 3 )

関数の内部で引数の配列を変数としてそのまま利用していると 変更した内容が、元の配列に反映されてしまします。

PHPのマニュアルにも書いてあります。

[参考]
PHP: リファレンスが行うことは何ですか? - Manual

通常あまり発生することではないと思いますが それゆえに忘れがちで気づきにくいですね。

Google サイト内検索

Amazonアソシエイト