2012-09-07 16 views
12

Tengo una duda en php foreach iteration.Php foreach: ¿Por qué no anula el valor de la matriz al iterar?

Mire mi código de abajo.

CÓDIGO:

$arr=array(1,2,3); 

    echo '$arr value : '. $arr; 

    echo '<br>'; 

    foreach($arr as $arr){ 
     echo $arr.'<br>'; 
    } 
    echo '$arr value : '. $arr; 

SALIDA:

$arr value : Array 
1 
2 
3 
$arr value : 3 

Mientras que la iteración gama i utilizado mismo nombre de la matriz de valor clave foreach($arr as $arr) pero funciona bien. ¿Cómo está funcionando?

¿Por qué no anula el valor de la matriz al iterar?

Quiero saber cómo funciona la iteración foreach.

Por favor, ¡ayúdame!

Gracias de antemano Logan

+2

Eso es definitivamente una salida sorprendente. –

+0

doesnt php de alguna manera almacena en caché el contenido del $ arr original (el arreglo), luego mientras se repite, cambia y muestra el $ arr (como 1, 2 y 3), luego al final el $ arr queda como "3" , ya que simplemente no guarda el valor almacenado en caché, vuelve al archivo original, porque php no espera que lo anule ... –

+0

Es sorprendente. –

Respuesta

13

Por qué no anula el valor de la matriz al iterar?

foreach trabajará en una copia de la matriz original así que las cosas que cambie en el bucle foreach no cambiarán los valores que se recorre de nuevo.

+1

Emil con la fácil ganancia de Rep. Bien hecho;) jeje +1! –

-2

foreach evalúa primero el lado izquierdo antes de iterar sobre sus elementos. Por lo tanto, la reasignación al nombre $ arr no modifica $ arr.

Además, la variable de bucle fugas en el contexto exterior, como documented:

de referencia de un $value y el último elemento de la matriz se mantienen incluso después del bucle foreach. Se recomienda destruirlo por unset().

Por supuesto, para evitar la confusión, simplemente debe utilizar un nombre diferente para la variable de bucle que para la matriz que estés bucle sobre: ​​

$arr=array(1,2,3); 
foreach($arr as $a) { // Note the "as $a", not "as $arr" 
    echo $a.'<br>'; 
} 
echo '$arr value : '. $arr; 
+5

Creo que esa es la pregunta: ¿por qué funciona de la forma en que lo hace cuando las variables tienen el mismo nombre? –

+0

@MarekKarbarz Enmendó la respuesta con eso. – phihag

0

$ arr y $ arr son los mismos en su código.La matriz de origen y la variable de referencia tienen el mismo nombre. Por lo tanto, foreach conserva el valor que se recibió por última vez y no renuncia a la variable.

-1

Hmm, después de un poco de investigación me encontré con este código:

<?php 
$arr=array(1,2,3); 

echo '$arr value : '. $arr; 

echo '<br>'; 

foreach($arr as $arr){ 
    echo $arr.'<br>'; 
} 

foreach($arr as $key) { 
    echo $key.'<br>'; 
} 
echo '$arr value : '. $arr; 

Qué tenía esta salida:

$arr value : Array 
1 
2 
3 
PHP Warning: Invalid argument supplied for foreach() in ...file... 

Mi lectura de esto es que la segunda $arr se cubrían el primero uno mientras está dentro del lazo foreach, pero tan pronto como sale del lazo foreach desata internamente el símbolo ($arr)

+2

No lo desarma, lo anula con el último valor que tiene el 'foreach' en el ciclo. Entonces el segundo 'foreach' está tratando de recorrer un único valor, no una matriz –

+0

Ni siquiera pensé en eso, eso es aún peor. –

0

foreach utilizar una copia de la matriz original, por lo que se podría pensar el código

foreach($arr as $arr){ 
    echo $arr.'<br>'; 
} 

es como a continuación:

for ($i = 0, $arr_tmp = $arr, $len = count($arr_tmp); $i < $len; $i++) { 
    $arr = $arr_tmp[$i]; 
    echo $arr.'<br>'; 
} 

Esto explica por qué el $arr es 3 al fin.

3

PHP utiliza un mecanismo copy on write o lazy copy con reference counting para el manejo de la memoria.

En la primera etapa de la iteración foreach, $arr es "suave copiado" (sin copia real, pero sólo se aumenta la refcount del zval de $array). pago variable container and label de variables de PHP.

En nuestro caso,

  • primero mantiene una referencia al real $arr variable y el primer valor de la matriz se obtiene de punto de referencia.
  • para su uso posterior primero elemento de la matriz se le asigna a segunda $arr foreach ($ arr como $ matriz)
  • En la siguiente iteración, segundo valor de la matriz se obtiene de punto de referencia previamente guardada, y se asigna ese valor a mismo $arr y continúa.
  • Como el valor de $arr se cambia dentro del ciclo, no puede imprimir ese conjunto fuera del ciclo utilizando la variable $arr.

espero que puedan entender ...

Para un estudio en profundidad de pagar http://www.php.net/manual/en/internals2.opcodes.fe-fetch.php y http://www.php.net/manual/en/internals2.opcodes.fe-reset.php

Curiosamente se puede jugar con esto también ...

current() dentro de un bucle foreach siempre devolverá el mismo elemento !!!

Código

$source = array(10, 20, 30); 
foreach ($source as $value) { 
    echo 'Value is ', $value, ', and current() is ', current($source), '<br>'; 
} 

salida

Value is 10, and current() is 20 
Value is 20, and current() is 20 
Value is 30, and current() is 20 
0

que está sobre la escritura de la matriz cuando se trae un registro, que está pidiendo el código en busca de un récord de $ matriz y poner en la matriz llamada $ arr, por lo que está escribiendo la matriz completa con un solo parámetro antes de $ arr = {1,2,3}; después de esta línea y la primera iteración foreach ($ matriz como $ matriz) ya la del $ matriz es igual a 3, que el último elemento de la matriz, espero que bajo el soporte del problema

1
foreach ($arr as $arr) { 
    // code 
} 

Esto puede ser confuso para usted porque su modelo mental de cómo funciona esto es:

  1. PHP toma el elemento actual de $arr y avanza el puntero
  2. asigna el valor a $arr
  3. ejecuta // code
  4. se repite desde el paso uno

lo que realmente hace es sin embargo esto (o, al menos, una simplificación aproximada de la misma):

  1. PHP inicia la operación foreach, teniendo la valor de matriz que está asociado con $arr
  2. pone esta matriz en algún lugar internamente, digamos un var iterator
  3. que toma s el elemento actual de var iterator y avanza el iterador
  4. asigna el valor que se tardó en $arr en el script
  5. ejecuta // code
  6. se repite desde el paso 3

En otras palabras, se hace no tome el siguiente valor desde $arr en cada iteración, solo lo usó una vez para obtener el iterador inicial. La cosa real que itera se almacena internamente y ya no está asociada con $arr. Eso significa que $arr es gratuito para otros fines en su secuencia de comandos y PHP se complace en reutilizarlo en cada iteración. Una vez hecho el ciclo, el último elemento permanece en $arr.

Si conoces funciones anónimas, tal vez esto ilustra mejor por qué esto funciona de la forma en que funciona:

foreach($arr, function ($arr) { 
    // code 
}); 

La implementación de una función de este tipo foreach puede ser simplemente esto:

function foreach(array $array, callable $code) { 
    while (list(, $value) = each($array)) { 
     $code($value); 
    } 
} 
+0

+1, excepto que su ejemplo ilustrativo al final no explica por qué '$ arr' se cambia después del ciclo :-) –

+0

Bueno, sí, en la función anónima, el' $ arr' no se filtra en el ámbito circundante . Eso es realmente lo menos complicado que pensaría, porque la "variable de bucle sigue estando disponible después del bucle y tiene el último valor", funciona igual independientemente del nombre de la variable ... :) – deceze

Cuestiones relacionadas