foreachで連想配列に代入した後はcurrentが変わるのでwhileでeachするとハマる

へぇ、phpってこういう動きするんだーと思ったので。
普段while each使わないのでハマったことなかったのだけど、何かbugがあるなぁと思うコードを見てみたらforeachの後にwhile使ってるのが原因ってことがわかった。



bugをわかりにくくしていたのは以下のことがあったから。

  • foreachしてるでカーソルは最後まで進む
  • ただし、foreachの中で元の連想配列に代入していた場合にはカーソルが2つめになる

このせいでwhileが中途半端に成功してるのがbugに繋がった。

<?php
$hash = array(
    'a' => 1,
    'b' => 2,
    'c' => 3,
);

var_dump('current => ' . current($hash)); // string(20) "before: current => 1"

foreach ($hash as $key => $val) {
}

var_dump('foreach: current => ' . current($hash)); // string(19) "after: current => "

foreach ($hash as $key => $val) {
    $hash[$key] = $val;
}

var_dump('foreach + insert: current => ' . current($hash)); // string(19) "after: current => 2"

while (list($key, $val) = each($hash)) {
    var_dump($key, $val);
}

// string(1) "b"
// int(2)
// string(1) "c"
// int(3)

refs. PHP: each - Manual