Ver Mensaje Individual
  #3 (permalink)  
Antiguo 12/08/2014, 11:57
Avatar de hhs
hhs
Colaborador
 
Fecha de Ingreso: junio-2013
Ubicación: México
Mensajes: 2.995
Antigüedad: 11 años, 5 meses
Puntos: 379
Respuesta: Extraño comportamiento de foreach

Código PHP:
Ver original
  1. <?php
  2.     class A
  3.     {
  4.         public $datos = [1, 2, 3, 4, 5];
  5.        
  6.         public function __destruct()
  7.         {
  8.             echo("destruido");
  9.         }
  10.     }
  11.    
  12.     $test = new A();
  13.     foreach($test->datos as $test)
  14.     {
  15.         var_dump($test);
  16.     }    
  17.    
  18.     var_dump($test);
Lamento informar que este es el comportamiento esperado
  • El alcance de $test es global
  • foreach es una estructura
  • Destruct se llama de forma natural al final del script o donde se haga la ultima referencia al objeto
La ultima referencia al objeto es cuando se pasa el contenido de la propiedad datos al foreach es cuando se hace la llamada a destruct. y esto pasa por que en el foreach asigna cada valor de la iteración en $test (es global ) que ya no contiene el objeto si no 1 en la primera iteración por eso al final el ultimo var_dump tiene el valor de 5.
El segundo caso:
Código PHP:
Ver original
  1.    
  2.     foreach($test->datos as $test)
  3.     {
  4.         var_dump(memory_get_usage());
  5.         break; // Ojo con esto
  6.     }      
  7.    
  8.     var_dump($test);
Es similar pero aquí como no se itera solo una vez ya que el break finaliza el foreach de forma prematura, se pierde el arreglo liberando memoria.
Lo compruebas fácilmente ya que $test en el ultimo var_dump tiene el valor de cero.
Para solucionar el extraño "comportamiento" usa otro nombre de variable.
Código PHP:
Ver original
  1. class A
  2. {
  3.     public $datos = [1, 2, 3, 4, 5];
  4.  
  5.     public function __destruct()
  6.     {
  7.         echo("destruido");
  8.     }
  9. }
  10.  
  11. $test = new A();
  12.  
  13. var_dump($test);
  14.  
  15. foreach($test->datos as $dato)
  16. {
  17.     var_dump($dato);
  18. }
  19.  
  20. var_dump($test);
La salida se comporta como esperabas:
Cita:
object(A)[1]
public 'datos' =>
array (size=5)
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5

int 1

int 2

int 3

int 4

int 5

object(A)[1]
public 'datos' =>
array (size=5)
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5

destruido
Creo que esto será una buena pregunta para examen
__________________
Saludos
About me
Laraveles
A class should have only one reason to change.