После первого цикла foreach, $itemвсе еще остается ссылка на некоторое значение, которое также используется $arr[2]. Таким образом, каждый вызов foreach во втором цикле, который не вызывается по ссылке, заменяет это значение и, таким образом $arr[2], новым значением.
Таким образом, цикл 1, значение и $arr[2]стать $arr[0], что является 'Foo'.
Цикл 2, значение и $arr[2]стать $arr[1], который является «бар».
Цикл 3, значение и $arr[2]стать $arr[2], который является «бар» (из-за цикла 2).
Значение baz фактически теряется при первом вызове второго цикла foreach.
Отладка вывода
Для каждой итерации цикла мы будем $itemвыводить значение, а также рекурсивно выводить массив$arr .
Когда первый цикл проходит, мы видим этот вывод:
foo
Array ( [0] => foo [1] => bar [2] => baz )
bar
Array ( [0] => foo [1] => bar [2] => baz )
baz
Array ( [0] => foo [1] => bar [2] => baz )
В конце цикла $itemвсе еще указывает на то же место, что и $arr[2].
Когда второй цикл проходит, мы видим этот вывод:
foo
Array ( [0] => foo [1] => bar [2] => foo )
bar
Array ( [0] => foo [1] => bar [2] => bar )
bar
Array ( [0] => foo [1] => bar [2] => bar )
Вы заметите, как каждый раз, когда массив помещает новое значение $item, он также обновляется $arr[3]тем же значением, так как они все еще указывают на одно и то же местоположение. Когда цикл достигает третьего значения массива, он будет содержать значение, barпотому что оно было просто установлено предыдущей итерацией этого цикла.
Это ошибка?
Нет. Это поведение ссылочного элемента, а не ошибка. Это было бы похоже на запуск чего-то вроде:
for ($i = 0; $i < count($arr); $i++) { $item = $arr[$i]; }
Цикл foreach не является особенным по своей природе, в котором он может игнорировать ссылочные элементы. Это просто установка этой переменной на новое значение каждый раз, как если бы вы были вне цикла.