Après la première boucle foreach, il $item
y a toujours une référence à une valeur qui est également utilisée par $arr[2]
. Ainsi, chaque appel foreach dans la deuxième boucle, qui n'appelle pas par référence, remplace cette valeur, et donc $arr[2]
, par la nouvelle valeur.
Donc boucle 1, la valeur et $arr[2]
devenir $arr[0]
, qui est «toto».
Boucle 2, la valeur et $arr[2]
devenir $arr[1]
, qui est «bar».
Boucle 3, la valeur et $arr[2]
devenir $arr[2]
, qui est «bar» (à cause de la boucle 2).
La valeur «baz» est en fait perdue au premier appel de la deuxième boucle foreach.
Débogage de la sortie
Pour chaque itération de la boucle, nous allons faire écho à la valeur de $item
et imprimer récursivement le tableau $arr
.
Lorsque la première boucle est exécutée, nous voyons cette sortie:
foo
Array ( [0] => foo [1] => bar [2] => baz )
bar
Array ( [0] => foo [1] => bar [2] => baz )
baz
Array ( [0] => foo [1] => bar [2] => baz )
À la fin de la boucle, $item
pointe toujours vers le même endroit que $arr[2]
.
Lorsque la deuxième boucle est exécutée, nous voyons cette sortie:
foo
Array ( [0] => foo [1] => bar [2] => foo )
bar
Array ( [0] => foo [1] => bar [2] => bar )
bar
Array ( [0] => foo [1] => bar [2] => bar )
Vous remarquerez que chaque fois que le tableau insère une nouvelle valeur $item
, il est également mis $arr[3]
à jour avec la même valeur, car ils pointent toujours vers le même emplacement. Lorsque la boucle atteint la troisième valeur du tableau, elle contiendra la valeur bar
car elle vient d'être définie par l'itération précédente de cette boucle.
Est-ce un bug?
Non. Il s'agit du comportement d'un élément référencé et non d'un bogue. Ce serait similaire à exécuter quelque chose comme:
for ($i = 0; $i < count($arr); $i++) { $item = $arr[$i]; }
Une boucle foreach n'est pas de nature spéciale dans laquelle elle peut ignorer les éléments référencés. Il s'agit simplement de définir cette variable sur la nouvelle valeur à chaque fois, comme vous le feriez en dehors d'une boucle.