2010-04-15 6 views
5

Si je parcourt deux fois un tableau, une fois par référence puis par valeur, PHP écrasera la dernière valeur du tableau si j'utilise le même nom de variable pour chaque boucle. Ceci est mieux illustré par un exemple:Pourquoi PHP écrase-t-il des valeurs lorsque je parcourt deux fois ce tableau (par référence, par valeur)

$array = range(1,5); 
foreach($array as &$element) 
{ 
    $element *= 2; 
} 
print_r($array); 
foreach($array as $element) { } 
print_r($array); 

sortie:

Array ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10)

Array ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 8)

Notez que je ne suis pas Je cherche une solution, je cherche à comprendre pourquoi cela se passe. Notez également que cela ne se produit pas si les noms de variables dans chaque boucle ne sont pas tous $element, donc je suppose qu'il s'agit de $element toujours dans la portée et une référence après la fin de la première boucle.

Répondre

7

Après la première boucle $ element est toujours une référence au dernier élément/valeur de $ array.
Vous pouvez voir que lorsque vous utilisez var_dump() au lieu de print_r()

array(5) { 
    [0]=> 
    int(2) 
... 
    [4]=> 
    &int(2) 
} 

Notez que & dans &int(2).
Avec la deuxième boucle, vous affectez des valeurs à l'élément $. Et comme c'est toujours une référence, la valeur dans le tableau est également modifiée. Essayez-le avec

foreach($array as $element) 
{ 
    var_dump($array); 
} 

comme la deuxième boucle et vous verrez.
Il est donc plus ou moins les mêmes que

$array = range(1,5); 
$element = &$array[4]; 
$element = $array[3]; 
// and $element = $array[4]; 
echo $array[4]; 

(uniquement avec des boucles et la multiplication ... hey, je l'ai dit "plus ou moins" ;-))

+0

Merci! Cela a un sens complet. –

5

est ici an explanation from the man himself:

$y = "some test"; 

foreach ($myarray as $y) { 
    print "$y\n"; 
} 

$y Ici, $y est une entrée de table de symboles faisant référence à une chaîne contenant "quelques test". Sur la première itération vous faites essentiellement:

$y = $myarray[0]; // Not necessarily 0, just the 1st element 

Alors maintenant, le stockage associé à $y est remplacée par la valeur de $myarray. Si $y est associé à un autre stockage via une référence , ce stockage sera modifié.

Maintenant, disons que vous faites ceci:

$myarray = array("Test"); 
$a = "A string"; 
$y = &$a; 

foreach ($myarray as $y) { 
    print "$y\n"; 
} 

Ici $y est associé au même stockage que $a à travers une référence pour lorsque la première itération fait:

$y = $myarray[0]; 

Le seul endroit cette chaîne "Test" peut aller dans le stockage associé à $y.

1

Voici comment vous résoudre ce problème:

foreach($array as &$element) 
{ 
    $element *= 2; 
} 
unset($element); #gets rid of the reference and cleans the var for re-use. 

foreach($array as $element) { }