PHPのforeachで代入される変数に気をつける

ヨメレバCSS
オリジナルCSS

 foreachを書いているとき、意図せず変数が変化してたことがあったので少し確認してみました。

スポンサーリンク
GoogleAdSence レクタングル(大)

PHPのforeachでは変数に代入される

環境はPHP 7.2.7です。

<?php
$val1 = 1;

foreach([2, 3, 4, 5] as $val1) {
    printf("in foreach $val1\n");
}

printf("val1: $val1\n");

これを実行すると、

in foreach 2
in foreach 3
in foreach 4
in foreach 5
val1: 5

こうじゃ。

 val1が代入されて変化してしまっています。

 ローカル変数として定義していたものとforeachを回すときに使っていた変数の変数名がたまたま同じものになったとき、foreach抜けたらローカル変数のほうが変わってて最初気付かなかったところです。foreachのkeyとvalueって意識的には一時的なものとしか思ってなくて。

 このへんを踏まえて公式ドキュメントを見ると、foreachの「警告」と書かれている項にある、参照を使った事例はだいぶイヤな予感しかしない

 

 foreachで使う変数はだいたいループないでのテンポラリ的な扱いのつもりで、「$k => $v」とか割と適当に設定したりしてますから、迂闊に参照を絡めたりするとなんでそうなるのかわからないバグとかになりそうです。

pythonの場合

 今をときめくPython(3.5.2)。

val1 = 1

for val1 in [2, 3, 4, 5]:
    print("in foreach "+str(val1))

print ("val1: "+str(val1))

これを実行すると

in foreach 2
in foreach 3
in foreach 4
in foreach 5
val1: 5

こうじゃ。

 やっぱりval1が変化しています。

rubyの場合

 ruby (2.4.2p198)の場合も、

val1 = 1

for val1 in 2..5
    print("in foreach ", val1, "\n")
end

print("val1: ", val1, "\n")

やっぱりこう。

in foreach 2
in foreach 3
in foreach 4
in foreach 5
val1: 5

 あとrubyにはeachメソッドがあり、

val1 = 1

range = 2..5
range.each{|val1|
  print("in each ", val1, "\n")
}

print("val1: ", val1, "\n")

そちらを使うと

in each 2
in each 3
in each 4
in each 5
val1: 1

こうじゃ。

 eachの実行だとブロックの中に隔離される感じでしょうか。

スポンサーリンク
GoogleAdSence レクタングル(大)

シェアする

スポンサーリンク
GoogleAdSence レクタングル(大)