2010-05-06 19 views
6

Estoy tratando de entender el comportamiento de constructor y destructor de php. Todo va según lo esperado con el constructor, pero estoy teniendo problemas para que el destructor se dispare implícitamente. He hecho toda la lectura en php.net y sitios relacionados, pero no puedo encontrar una respuesta a esta pregunta.comportamiento de php destructor

Si tengo una clase simple, algo así como:

class test{ 

    public function __construct(){ 
      print "contructing<br>"; 
    } 

    public function __destruct(){ 
      print "destroying<br>"; 
    } 
} 

y lo llamo con algo como:

$t = new test; 

se imprime el mensaje de constructor. Sin embargo, esperaría que cuando las secuencias de comandos finalicen y la página se muestre, el destructor debería dispararse. Por supuesto que no.

Si llamo unset ($ t); cuando los guiones finalizan, por supuesto, el destructor dispara, pero ¿hay alguna manera de hacer que dispare implícitamente?

gracias por cualquier consejo

+3

Bienvenido al desbordamiento de la pila :) –

Respuesta

4

Se ejecuta la función mágica __destruct() cuando se elimina/destruido el objeto (usando unset). No se llama durante el cierre de un script. Cuando un script PHP termina de ejecutarse, limpia la memoria, pero no 'borra' los objetos como tales, por lo tanto, no se invocan los métodos __destruct().

Quizás esté pensando en el register_shutdown_function(), que se activa cuando su script PHP termina de ejecutarse.

function shutdown() 
{ 
    // code here 
    echo 'this will be called last'; 
} 

register_shutdown_function('shutdown'); 
+0

bien, gracias por la explicación – kris

+10

En realidad, de acuerdo con el manual esto no es cierto. Ver http://php.net/manual/en/language.oop5.decon.php. "Se llamará al método destructor tan pronto como se eliminen todas las referencias a un objeto en particular o cuando el objeto se destruya explícitamente o en cualquier orden en la secuencia de apagado." –

+2

Debe tener mucho cuidado al intentar escribir en el navegador en una función de apagado -" Se llaman las funciones de apagado después de cerrar todos los búferes de salida abiertos "- althuogh stdout todavía está conectado, esta puede no ser la secuencia de salida que estaba utilizando previamente – symcbean

3

Mi comprensión es que los destructores son llamados automáticamente para cualquier objeto restante cuando termina el guión.

Mirando el manual page on constructors and destructors, parece que la única manera de evitar completamente los destructores es si llama al exit() desde el destructor de un objeto que se destruye antes del objeto en cuestión.

¿Está utilizando exit() en cualquiera de sus destructores? ¿Hay incluso varios objetos en tu script?

Si no es demasiado problema, quizás podría publicar el código real en cuestión en lugar del código de muestra que tiene en su pregunta ahora. Aparte del error tipográfico en el constructor de la muestra, ese código debe llamar al tanto el constuctor como el destructor para su objeto test.

+2

Creo que es más complicado que eso. Si pones una 'exit' en un destructor entonces la primera vez que el objeto es destruido llamará a cualquier función registrada con 'register_shutdown_function' y luego llamará a otros destructores. Si esos destructores también contienen una 'salida', el guión se detendrá allí. Es decir, la primera llamada para salir pone al script en modo de apagado, el segundo lo fuerza para detenerlo inmediatamente. A menos que la segunda salida esté dentro de la función de apagado, esa se comporta más o menos como un 'retorno'. – mpen

9

Esto es bastante fácil de probar.

<?php 

class DestructTestDummy { 
    protected $name; 

    function __construct($name) { 
     echo "Constructing $name\n"; 
     $this->name = $name; 
    } 

    function __destruct() { 
     echo "Destructing $this->name\n"; 
     //exit; 
    } 
} 

echo "Start script\n"; 

register_shutdown_function(function() { 
    echo "Shutdown function\n"; 
    //exit 
}); 

$a = new DestructTestDummy("Mr. Unset"); 
$b = new DestructTestDummy("Terminator 1"); 
$c = new DestructTestDummy("Terminator 2"); 

echo "Before unset\n"; 
unset($a); 
echo "After unset\n"; 


echo "Before func\n"; 
call_user_func(function() { 
    $c = new DestructTestDummy("Mrs. Scopee"); 
}); 
echo "After func\n"; 

$b->__destruct(); 

exit("Exiting\n"); 

En PHP 5.5.12 esta imagen Impresiones:

Start script 
Constructing Mr. Unset 
Constructing Terminator 1 
Constructing Terminator 2 
Before unset 
Destructing Mr. Unset 
After unset 
Before func 
Constructing Mrs. Scopee 
Destructing Mrs. Scopee 
After func 
Destructing Terminator 1 
Exiting 
Shutdown function 
Destructing Terminator 2 
Destructing Terminator 1 

Así podemos ver que se llama al destructor cuando explícitamente desarmar el objeto, cuando se sale del ámbito, y cuando el script termina.