2010-05-06 15 views
6

sto cercando di capire il comportamento del costruttore e del distruttore. Tutto procede come previsto con il costruttore, ma ho difficoltà a far sì che il distruttore funzioni in modo implicito. Ho fatto tutte le letture su php.net e sui siti correlati, ma non riesco a trovare una risposta a questa domanda.comportamento distruttore php

Se ho una semplice classe, qualcosa di simile:

class test{ 

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

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

e mi chiamo con qualcosa di simile:

$t = new test; 

stampa il messaggio costruttore. Tuttavia, mi aspetterei che quando gli script terminano e la pagina sia visualizzata, il distruttore dovrebbe attivarsi. Certo che non lo è.

Se chiamo non impostato ($ t); quando finisce la sceneggiatura, naturalmente il fuoco del distruttore, ma c'è un modo per farlo scattare implicitamente?

grazie per eventuali suggerimenti

+3

Benvenuti a stack overflow :) –

risposta

4

viene eseguita la funzione magica __destruct() quando l'oggetto viene eliminato/distrutto (utilizzando unset). Non viene chiamato durante l'arresto di uno script. Quando uno script PHP termina l'esecuzione, pulisce la memoria, ma non "cancella" gli oggetti come tali, quindi i metodi __destruct() non vengono chiamati.

Si potrebbe pensare allo register_shutdown_function(), che viene attivato quando lo script PHP termina l'esecuzione.

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

register_shutdown_function('shutdown'); 
+0

OK, grazie per la spiegazione – kris

+10

In realtà, secondo il manuale questo non è vero. Vedi http://php.net/manual/en/language.oop5.decon.php. "Il metodo del distruttore verrà chiamato non appena tutti i riferimenti a un particolare oggetto vengono rimossi o quando l'oggetto viene esplicitamente distrutto o in qualsiasi ordine nella sequenza di spegnimento." –

+2

Devi stare molto attento a provare a scrivere sul browser in una funzione di spegnimento -" Le funzioni di spegnimento vengono chiamate dopo aver chiuso tutti i buffer di output aperti "- anche se lo stdout è ancora connesso, questo potrebbe non essere il flusso di output che stavi utilizzando in precedenza – symcbean

3

La mia comprensione è che i distruttori vengono automaticamente chiamati per qualsiasi oggetto rimanente al termine dello script.

Guardando allo manual page on constructors and destructors, sembra che l'unico modo per ignorare completamente i distruttori sia se si chiama exit() dal distruttore di un oggetto che viene distrutto prima dell'oggetto in questione.

Stai utilizzando exit() in uno dei tuoi distruttori? Ci sono anche più oggetti nel tuo script?

Se non ci sono troppi problemi, forse potresti pubblicare il codice in questione piuttosto che il codice di esempio che hai nella tua domanda. A parte l'errore di battitura nel costruttore di esempio, il codice deve chiamare sia il costruttore che il distruttore per l'oggetto test.

+2

Penso che sia più complicato di così: se metti un 'exit' in un distruttore, la prima volta che l'oggetto viene distrutto chiamerà qualsiasi funzione registrata con 'register_shutdown_function' e quindi chiamerà qualsiasi altro distruttore.Se quei distruttori contengono anche un' exit', allora lo script si fermerà qui, cioè, la prima chiamata per uscire mette lo script in modalità shutdown, il secondo lo forza fermarsi immediatamente, a meno che la seconda uscita non sia all'interno della funzione di spegnimento, che si comporti più o meno come un "ritorno". – mpen

9

Questo è abbastanza facile da testare.

<?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"); 

In PHP 5.5.12 Questo stampa:

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 

Così possiamo vedere che il distruttore viene chiamato quando abbiamo esplicitamente disinserito l'oggetto, quando va fuori portata, e quando il la sceneggiatura finisce