やったこと

webサービスを作るときに考えたことを垂れ流します

PHPのforeachを参照渡しで回したら最後の要素が上書きされちゃった!

PHPのforeachを参照渡しで回したら最後の要素が別の値に上書きされてしまったという話。
以下のコードをご覧下さい。

$test1 = array("111","222","333");
$test2 = array("aaa","bbb","ccc");

foreach($test1 as &$val){}
foreach($test2 as $val){}

print_r($test1);
print_r($test2);


test1の配列とtest2の配列をforeachで回しただけで何もいじってはいません。この結果をプリント出力すると。

Array
(
    [0] => 111
    [1] => 222
    [2] => ccc
)
Array
(
    [0] => aaa
    [1] => bbb
    [2] => ccc
)

となる。test1の最後の要素がtest2の最後の要素に上書きされてしまっている・・・。

これは、始めのforeachのループを抜けたあとも「&$val」の参照が生きていて、二回目のforeachのときに次々に「&$val」の参照先に値をセットしてしまうために起きる現象。
けっこう有名な罠らしいんだけど、見事にはまってしまった・・。

これを回避するためには「unset」で参照をクリアすること。すなわち以下のように書くのが正解。

$test1 = array("111","222","333");
$test2 = array("aaa","bbb","ccc");

foreach($test1 as &$val){}
unset($val); //★ココ!
foreach($test2 as $val){}

print_r($test1);
print_r($test2);