2
votes

La boucle PHP foreach ne met pas à jour la valeur

Si le programme PHP ci-dessous est stocké dans bug.php, alors cette commande

<?php

    $A = array
    (
    "aa",
    "bb",
    );

    echo "Initial array\n";
    print_r($A);

    foreach ($A as $j => $line)
    {
        echo "j = $j  line = $line\n";
        echo "element $j is {$A[$j]}\n\n";

        if ($j == 0)
            $A[1] = "***" . $A[1];
    }

    echo "Final array\n";
    print_r($A);

?>

produira cette sortie lors de l'utilisation de PHP 7.0.33-0ubuntu0.16.04.1 (cli) ( NTS) Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies avec Zend OPcache v7.0.33-0ubuntu0.16.04.1, Copyright (c) 1999-2017, par Zend Technologies

Sortie:

Initial array
Array
(
    [0] => aa
    [1] => bb
)
j = 0  line = aa
element 0 is aa

j = 1  line = bb    <----------------------------------------------
element 1 is ***bb  <----------------------------------------------

Final array
Array
(
    [0] => aa
    [1] => ***bb
)

Notez le lignes marquées ci-dessus. L'élément $ A [1] est "*** bb", mais $ line - que le foreach devrait associer à la clé 1 - est "bb".

S'agit-il d'un bogue, ou y a-t-il une subtilité PHP dont je ne suis pas conscient?

php bug.php


3 commentaires

Vous avez modifié $ A [1] lors du premier passage dans le foreach afin qu'il contienne maintenant *** bb que vous affichez ensuite le deuxième passage via le foreach . Cela semble tout à fait correct d'où je suis assis.


Quel est votre résultat attendu, il n'est pas clair.


@Dave Je ne pense pas que vous compreniez pleinement la question et l'exemple.


3 Réponses :


0
votes

Sauf si le tableau est référencé, foreach () opère sur une copie du tableau spécifié et non sur le tableau lui-même. foreach a des effets secondaires sur le pointeur de tableau. Ne vous fiez pas au pointeur de tableau pendant ou après le foreach sans le réinitialiser.

Ainsi, lorsque vous modifiez $ A [1] , vous modifiez le tableau original , pas la copie que le foreach () utilise ensuite la boucle.

Cette distinction importante semble actuellement absente de la documentation officielle , mais vous pouvez en savoir plus ici: Comment fonctionne réellement PHP «foreach»?


0 commentaires

0
votes

Comme mentionné dans les notes sur php.net, à moins que le tableau ne soit référencé, foreach fonctionne sur une copie du tableau spécifié et non sur le tableau lui-même. Vous sortez une variable à partir de la copie d'origine, puis du tableau modifié.


0 commentaires

0
votes

Le tableau est transmis au foreach en tant que copie - sauf si vous le transmettez comme référence (indiquez-le en ajoutant un & à $ value ) cela ne reflétera pas les mises à jour de la valeur que vous effectuez dans la première itération.

Considérez ceci: p>

foreach ($A as $j => &$line)
{
    echo "j = $j  line = $line\n";
    echo "element $j is {$A[$j]}\n\n";

    if ($j == 0)
       $A[1] = "***" . $A[1];
}
/* Will output:

 * j = 0  line = aa
 * element 0 is aa
 *
 * j = 1  line = ***bb
 * element 1 is ***bb
 */

Vous voyez la & line qui signifie que nous passons dans le bloc une référence et maintenant tout changement est reflété dans le tableau et non dans un $ line copie du tableau initial que vous avez passé dans le bloc de boucle.

J'espère avoir été clair ...

J'ai remarqué que la documentation le dit exactement: p >

Cela dit exactement dans la documentation :) p>

Afin de pouvoir modifier directement les éléments du tableau dans la boucle, faites précéder $ value de &. Dans ce cas, la valeur sera attribuée par référence.


0 commentaires