Po pierwszej pętli foreach $item
nadal znajduje się odniesienie do jakiejś wartości, z której również korzysta $arr[2]
. Zatem każde wywołanie foreach w drugiej pętli, które nie wywołuje przez odwołanie, zastępuje tę wartość, a tym samym $arr[2]
nową wartością.
Więc pętla 1, wartość i $arr[2]
get $arr[0]
, czyli „foo”.
Pętla 2, wartość i $arr[2]
staje się $arr[1]
, czyli „bar”.
Loop 3, wartość i $arr[2]
get $arr[2]
, czyli „bar” (z powodu pętli 2).
Wartość „baz” jest faktycznie tracona przy pierwszym wywołaniu drugiej pętli foreach.
Debugowanie danych wyjściowych
Dla każdej iteracji pętli będziemy powtarzać wartość, $item
a także rekurencyjnie wypisywać tablicę $arr
.
Po wykonaniu pierwszej pętli widzimy następujące dane wyjściowe:
foo
Array ( [0] => foo [1] => bar [2] => baz )
bar
Array ( [0] => foo [1] => bar [2] => baz )
baz
Array ( [0] => foo [1] => bar [2] => baz )
Na końcu pętli $item
nadal wskazuje to samo miejsce co $arr[2]
.
Po wykonaniu drugiej pętli widzimy następujące dane wyjściowe:
foo
Array ( [0] => foo [1] => bar [2] => foo )
bar
Array ( [0] => foo [1] => bar [2] => bar )
bar
Array ( [0] => foo [1] => bar [2] => bar )
Zauważysz, że za każdym razem, gdy tablica umieszcza nową wartość $item
, jest również aktualizowana $arr[3]
o tę samą wartość, ponieważ obie nadal wskazują to samo miejsce. Gdy pętla dotrze do trzeciej wartości tablicy, będzie zawierała wartość, bar
ponieważ została ustawiona przez poprzednią iterację tej pętli.
Czy to błąd?
Nie. To jest zachowanie przywoływanego elementu, a nie błąd. Byłoby to podobne do uruchomienia czegoś takiego:
for ($i = 0; $i < count($arr); $i++) { $item = $arr[$i]; }
Pętla foreach nie ma specjalnego charakteru, w którym może ignorować elementy, do których się odwołuje. Po prostu ustawia tę zmienną na nową wartość za każdym razem, jakbyś był poza pętlą.