Perché PHP sovrascrive i valori quando iterazione attraverso questo array due volte (per riferimento, per valore)
Domanda
Se iterazione attraverso un array due volte, una volta per riferimento e poi per valore, PHP sovrascriverà l'ultimo valore nell'array se utilizzo lo stesso nome variabile per ogni ciclo. Questo è meglio illustrato attraverso un esempio:
$array = range(1,5);
foreach($array as &$element)
{
$element *= 2;
}
print_r($array);
foreach($array as $element) { }
print_r($array);
Produzione:
Array ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 )
Array ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 8 )
Nota che non sto cercando una soluzione, sto cercando di capire perché sta accadendo. Si noti inoltre che non accade se i nomi delle variabili in ciascun ciclo non vengono chiamati ciascuno $element
, quindi immagino che abbia a che fare con $element
Ancora in portata e riferimento dopo la fine del primo ciclo.
Soluzione
Dopo il primo elemento loop $ è ancora un riferimento all'ultimo elemento/valore di $ array.
Puoi vederlo quando usi var_dump () invece di print_r ()
array(5) {
[0]=>
int(2)
...
[4]=>
&int(2)
}
Nota che e dentro &int(2)
.
Con il secondo ciclo assegni valori a $ elemento. E poiché è ancora un riferimento, anche il valore nell'array viene modificato. Provalo con
foreach($array as $element)
{
var_dump($array);
}
Come secondo ciclo e vedrai.
Quindi è più o meno uguale a
$array = range(1,5);
$element = &$array[4];
$element = $array[3];
// and $element = $array[4];
echo $array[4];
(Solo con loop e moltiplicazione ... Ehi, ho detto "più o meno" ;-))
Altri suggerimenti
Ecco una spiegazione dell'uomo stesso:
$y = "some test"; foreach ($myarray as $y) { print "$y\n"; }
Qui
$y
è una voce della tabella dei simboli che fa riferimento a una stringa contenente "qualche test". Nella prima iterazione che fai essenzialmente:$y = $myarray[0]; // Not necessarily 0, just the 1st element
Quindi ora l'archiviazione associata a
$y
è sovrascritto dal valore di$myarray
. Se$y
è associato ad qualche altro spazio di archiviazione attraverso un riferimento, che l'archiviazione verrà modificata.Ora diciamo che lo fai:
$myarray = array("Test"); $a = "A string"; $y = &$a; foreach ($myarray as $y) { print "$y\n"; }
Qui
$y
è associato allo stesso spazio di archiviazione$a
attraverso un riferimento, quindi quando la prima iterazione fa:$y = $myarray[0];
L'unico posto in cui può andare la stringa "test" è nell'archiviazione associata
$y
.
Ecco come risolveresti questo problema:
foreach($array as &$element)
{
$element *= 2;
}
unset($element); #gets rid of the reference and cleans the var for re-use.
foreach($array as $element) { }