Permettez-moi de préfixe en disant que ce que je sais de quoi foreach
est, et comment l'utiliser. Cette question concerne la façon dont il fonctionne sous le capot, et je ne veux pas de réponses allant dans le sens de "c'est comment vous boucle un tableau avec foreach
".
Pendant longtemps, j'ai supposé qu' foreach
a travaillé avec le tableau lui-même. Ensuite, j'ai trouvé beaucoup de références au fait qu'il travaille avec une copie de la matrice, et depuis, j'ai supposé que cela soit la fin de l'histoire. Mais j'ai récemment eu une discussion sur le sujet, et après un peu d'expérimentation trouvé que ce n'était pas vrai à 100%.
Laissez-moi vous montrer ce que je veux dire. Pour la suite de cas de test, nous allons travailler avec le tableau suivant:
$array = array(1, 2, 3, 4, 5);
foreach ($array as $item) {
echo "$item\n";
$array[] = $item;
}
print_r($array);
/* Output in loop: 1 2 3 4 5
$array after loop: 1 2 3 4 5 1 2 3 4 5 */
Cela montre clairement que nous ne sommes pas travailler directement avec la source de tableau - sinon la boucle continuera à jamais, car nous sommes toujours en poussant des éléments sur le tableau lors de la boucle. Mais juste pour être sûr que c'est le cas:
foreach ($array as $key => $item) {
$array[$key + 1] = $item + 2;
echo "$item\n";
}
print_r($array);
/* Output in loop: 1 2 3 4 5
$array after loop: 1 3 4 5 6 7 */
Cela nous conforte dans notre première conclusion, nous travaillons avec une copie de la source matrice au cours de la boucle, sinon, nous aurions voir les valeurs modifiées au cours de la boucle. Mais...
Si l'on regarde dans le manuel, on trouve cette déclaration:
Lorsque foreach première commence à s'exécuter, l'interne pointeur sur le tableau est automatiquement remise à zéro pour le premier élément du tableau.
Bon... ceci semble suggérer que l' foreach
s'appuie sur le tableau de pointeur du tableau source. Mais nous venons de prouver que nous sommes de ne pas travailler avec la source de tableau, à droite? Eh bien, pas tout à fait.
// Move the array pointer on one to make sure it doesn't affect the loop
var_dump(each($array));
foreach ($array as $item) {
echo "$item\n";
}
var_dump(each($array));
/* Output
array(4) {
[1]=>
int(1)
["value"]=>
int(1)
[0]=>
int(0)
["key"]=>
int(0)
}
1
2
3
4
5
bool(false)
*/
Ainsi, malgré le fait que nous ne sommes pas travailler directement avec la source de tableau, nous travaillons directement avec la source pointeur sur le tableau - le fait que le pointeur est à la fin du tableau à la fin de la boucle indique ce. Sauf que cela ne peut pas être vrai, si c'était le cas, cas de test 1 serait en boucle pour toujours.
Le manuel PHP indique également:
Comme foreach s'appuie sur l'interne pointeur sur le tableau de changer à l'intérieur de la boucle peut entraîner un comportement inattendu.
Bien, laissez-nous savoir ce que ce "comportement inattendu" est (techniquement, tout comportement est inattendu, car je ne sais plus à quoi m'attendre).
foreach ($array as $key => $item) {
echo "$item\n";
each($array);
}
/* Output: 1 2 3 4 5 */
foreach ($array as $key => $item) {
echo "$item\n";
reset($array);
}
/* Output: 1 2 3 4 5 */
...rien que des il y a, en fait, il semble à l'appui de la "copie de la source" de la théorie.
La Question
Ce qui se passe ici? Mon C-fu n'est pas assez bon pour moi de pouvoir extraire une conclusion correcte simplement en regardant le code source en PHP, je vous serais reconnaissant si quelqu'un pouvait traduire en anglais pour moi.
Il me semble qu' foreach
travaille avec une copie de la matrice, mais définit le pointeur sur le tableau de la source de tableau à la fin du tableau après la boucle.
- Est-ce correct et l'ensemble de l'histoire?
- Si non, quel est-il vraiment en train de faire?
- Est-il une situation où l'utilisation de fonctions qui permettent d'ajuster le pointeur sur le tableau (
each()
,reset()
et coll.) au cours d'uneforeach
pourrait affecter le résultat de la boucle?