Cita: Eso no es tan asi (o no me doy cuenta al menos, espero me tengas paciencia), considera el siguiente ejemplo similar al primero:
Código PHP:
Ver original$test = new A();
foreach($test as $test)
{
}
No se ve a simple vista, pero el $test que imprimes dentro del foreach ya no contiene el identificador del objeto por una simple y sencilla razón que estas pasando por alto. La variable $test que pasas al foreach y el que regresa están en el mismo ámbito debido a que el foreach no es una función $test no esta en un ámbito local, asi que la sobre escribe.
Entonces que es lo que pasa cuando iteras el objeto ?
Hasta aqui ya sabemos que $test se sobre escribe pero aun asi se itera el objeto y la razón ya te la respondiste.
Cita: El objeto solo se destruye cuando no hay mas identificadores definidos de ese objeto.
¿Es posible que el foreach realice una copia de ese identificador y por lo tanto pueda seguir iterando aunque la variable original ya haya cambiado de valor?
Php trata de forma diferente a los objetos por que su "referencia" se hace por el identificador que pasa a otras variables, por lo cual el foreach a nivel interno tiene que mantenerlo para no crear efectos adversos ya que el objeto puede estar "referenciado" en otras variables.
Esto lo comprobamos de forma sencilla:
Código PHP:
Ver originalclass A implements Iterator
{
private $datos = [1, 2, 3, 4, 5];
public function key() { return key($this->datos); } public function next() { return next($this->datos); } public function valid
() { return (key($this->datos) !== NULL && key($this->datos) !== FALSE); } public function __destruct()
{
echo("destruido");
}
}
$test = new A();
$test1 = $test; //pasamos identificador
foreach($test as $test)
{
}
var_dump($test); //se sobre escribe; ahora vale 5 var_dump($test1); //se mantiene el objeto echo 'Depues de esto se llama a __destruct <br>';
Despues de foreach el objeto original sigue con vida aun después de finalizar el ciclo y como se puede comprobar nuevamente $test se sobre escribe.
Si aun existe duda de si $test mantiene o no la referencia podemos probar algo: tu puedes llamar a __destruct si usas unset
Código PHP:
Ver originalclass A implements Iterator
{
private $datos = [1, 2, 3, 4, 5];
public function key() { return key($this->datos); } public function next() { return next($this->datos); } public function valid
() { return (key($this->datos) !== NULL && key($this->datos) !== FALSE); } public function __destruct()
{
echo("destruido");
}
}
$test = new A();
$test1 = $test; //pasamos identificador
foreach($test as $test)
{
}
var_dump($test); //se sobre escribe; ahora vale 5 var_dump($test1); //se mantiene el objeto echo 'Depues de esto se llama a __destruct <br>';
Si el $test sigue con el identificador debiera de detener de forma prematura el foreach al destruir el objeto y por ende tendríamos un resultado inesperado en $test1. Pero no es asi si ejecutas esto obtienes lo siguiente:
Cita: int 1
int 2
int 3
int 4
int 5
( ! ) Notice: Undefined variable: test in /home/hheredia/public_html/Curso/iteracion.php on line 56
Call Stack
# Time Memory Function Location
1 0.0022 236176 {main}( ) ../iteracion.php:0
null
object(A)[1]
private 'datos' =>
array (size=5)
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
Depues de esto se llama a __destruct
destruido
$test1 sigue integro con su referencia al objeto como es de esperarse junto con el notice de variable indefinida de $test.