Después del primer bucle foreach, $item
sigue siendo una referencia a algún valor que también está siendo utilizado por $arr[2]
. Por lo tanto, cada llamada foreach en el segundo bucle, que no llama por referencia, reemplaza ese valor y $arr[2]
, por lo tanto , con el nuevo valor.
Entonces, el bucle 1, el valor y el $arr[2]
devenir $arr[0]
, que es 'foo'.
Loop 2, el valor y $arr[2]
llegar a ser $arr[1]
, que es 'bar'.
Bucle 3, el valor y $arr[2]
llegar a ser $arr[2]
, que es 'bar' (debido al bucle 2).
El valor 'baz' en realidad se pierde en la primera llamada del segundo bucle foreach.
Depuración de la salida
Para cada iteración del bucle, haremos eco del valor $item
e imprimiremos recursivamente la matriz $arr
.
Cuando se ejecuta el primer ciclo, vemos esta salida:
foo
Array ( [0] => foo [1] => bar [2] => baz )
bar
Array ( [0] => foo [1] => bar [2] => baz )
baz
Array ( [0] => foo [1] => bar [2] => baz )
Al final del bucle, $item
sigue apuntando al mismo lugar que $arr[2]
.
Cuando se ejecuta el segundo ciclo, vemos esta salida:
foo
Array ( [0] => foo [1] => bar [2] => foo )
bar
Array ( [0] => foo [1] => bar [2] => bar )
bar
Array ( [0] => foo [1] => bar [2] => bar )
Notarás cómo cada matriz de tiempo pone un nuevo valor $item
, también se actualiza $arr[3]
con ese mismo valor, ya que ambos todavía apuntan a la misma ubicación. Cuando el bucle llega al tercer valor de la matriz, contendrá el valor bar
porque solo fue establecido por la iteración anterior de ese bucle.
¿Es un error?
No. Este es el comportamiento de un elemento referenciado, y no un error. Sería similar a ejecutar algo como:
for ($i = 0; $i < count($arr); $i++) { $item = $arr[$i]; }
Un bucle foreach no es de naturaleza especial en el que puede ignorar los elementos referenciados. Simplemente establece esa variable en el nuevo valor cada vez como lo haría fuera de un ciclo.