После первого цикла foreach, $item
все еще является ссылкой на некоторое значение, которое также используется $arr[2]
.Таким образом, каждый вызов foreach во втором цикле, который не вызывается по ссылке, заменяет это значение и, таким образом, $arr[2]
новым значением.
Таким образом, цикл 1, значение и $arr[2]
становятся $arr[0]
, что является 'foo'.
Цикл 2, значение и $arr[2]
становятся $arr[1]
, что является 'bar'.
Цикл 3, значение и $arr[2]
становятся $arr[2]
, что является'bar' (из-за цикла 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 не является особенным по своей природе, в котором он может игнорировать ссылочные элементы.Это просто установка этой переменной на новое значение каждый раз, как если бы вы были вне цикла.