2011-02-11 30 views
28
<?php 
    $a = array('a', 'b', 'c', 'd'); 

    foreach ($a as &$v) { } 
    foreach ($a as $v) { } 

    print_r($a); 
?> 

penso che sia un programma normale, ma questo è il risultato che sto ottenendo:strano comportamento del foreach

Array 
(
    [0] => a 
    [1] => b 
    [2] => c 
    [3] => c 
) 

Qualcuno può spiegare questo a me?

+4

Che cosa * "penso, il suo normale prog ma web ho visto op ......... allora .... ahh wat is it" * mean? –

+0

mi chiedo !!! Perché ottenere questo risultato ?? :) –

+1

@Bart Kiers: Sembra in stato confusionale. – BoltClock

risposta

67

Questo comportamento PHP è ben documentata Vedere le warning sulla pagina foreach di php.net

Attenzione

di riferimento di un valore di $ e l'ultimo elemento dell'array rimanere anche dopo il ciclo foreach. Si consiglia di distruggerlo con unset().

$a = array('a', 'b', 'c', 'd'); 

foreach ($a as &$v) { } 
unset($v); 
foreach ($a as $v) { } 

print_r($a); 

EDIT

tentativo di una guida step-by-step per ciò che sta realmente accadendo qui

$a = array('a', 'b', 'c', 'd'); 
foreach ($a as &$v) { } // 1st iteration $v is a reference to $a[0] ('a') 
foreach ($a as &$v) { } // 2nd iteration $v is a reference to $a[1] ('b') 
foreach ($a as &$v) { } // 3rd iteration $v is a reference to $a[2] ('c') 
foreach ($a as &$v) { } // 4th iteration $v is a reference to $a[3] ('d') 

          // At the end of the foreach loop, 
          // $v is still a reference to $a[3] ('d') 

foreach ($a as $v) { } // 1st iteration $v (still a reference to $a[3]) 
          // is set to a value of $a[0] ('a'). 
          // Because it is a reference to $a[3], 
          // it sets $a[3] to 'a'. 
foreach ($a as $v) { } // 2nd iteration $v (still a reference to $a[3]) 
          // is set to a value of $a[1] ('b'). 
          // Because it is a reference to $a[3], 
          // it sets $a[3] to 'b'. 
foreach ($a as $v) { } // 3rd iteration $v (still a reference to $a[3]) 
          // is set to a value of $a[2] ('c'). 
          // Because it is a reference to $a[3], 
          // it sets $a[3] to 'c'. 
foreach ($a as $v) { } // 4th iteration $v (still a reference to $a[3]) 
          // is set to a value of $a[3] ('c' since 
          //  the last iteration). 
          // Because it is a reference to $a[3], 
          // it sets $a[3] to 'c'. 
+0

lo so !!! Ma cosa c'è di sbagliato nel mio programma ??? –

+3

@Manish Trivedi: vedere la parte ** Warning ** per capire perché questo sta accadendo. Non c'è niente di sbagliato nel tuo programma. – BoltClock

+0

Grazie ..... ho capito –

2

Il primo ciclo foreach non fa alcuna modifica al array, proprio come ci aspetteremmo. Tuttavia, è necessario assegnare a $v un riferimento a ciascuno degli elementi di $a, in modo che, al termine del primo ciclo, $v sia, di fatto, un riferimento a $a[2].

Non appena viene avviato il secondo ciclo, a $v viene ora assegnato il valore di ciascun elemento . Tuttavia, $v è già un riferimento a $a[2]; pertanto, qualsiasi valore assegnato a verrà copiato automaticamente nell'ultimo elemento dell'array!

Così, durante la prima iterazione, $a[2] diventerà zero, quindi uno, e quindi uno di nuovo, essendo effettivamente copiato su se stesso. Per risolvere questo problema, è necessario impostare sempre per annullare le variabili che si utilizzano nei cicli foreach di riferimento foreach o, meglio ancora, evitare di utilizzare il primo insieme.