class MyDestructableClass {
function __construct() {
print "\nIn constructor\n";
$this->name = "MyDestructableClass";
}
function __destruct() {
print "\nDestroying " . $this->name . "\n";
}
}
$obj = new MyDestructableClass();
Lorsque le script ci-dessus est dans un environnement complexe, le __destruct
ne sera pas appelé lorsque exit
, mais je ne peux pas le reproduire facilement. Quelqu'un l'a-t-il déjà remarqué?
MODIFIER
Je vais poster tout ça ici, c'est l'environnement de test de symfony, ce qui signifie que vous pouvez facilement le reproduire si vous connaissez le framework:
require_once dirname(__FILE__).'/../bootstrap/Doctrine.php';
$profiler = new Doctrine_Connection_Profiler();
$conn = Doctrine_Manager::connection();
$conn->setListener($profiler);
$t = new Lime_test(0, new Lime_output_color());
class MyDestructableClass {
function __construct() {
print "\nIn constructor\n";
$this->name = "MyDestructableClass";
}
function __destruct() {
print "\nDestroying " . $this->name . "\n";
}
}
$obj = new MyDestructableClass();
$news = new News();
$news->setUrl('http://test');
$news->setHash('http://test');
$news->setTitle('http://test');
$news->setSummarize('http://test');
$news->setAccountId(1);
$news->setCategoryId(1);
$news->setThumbnail('http://test');
$news->setCreatedAt(date('Y-m-d H:i:s',time()));
$news->setUpdatedAt(date('Y-m-d H:i:s',time()));
$news->save();
exit();
Le __destruct
sera pas appelé:
exit
est appelé dans un autre destructeurexit
est appelé dans une fonction d'arrêt enregistrée avec register_shutdown_function
Je suppose que c'est tout ce à quoi je peux penser en ce moment
& Ce que Pascal MARTIN a dit. C'est la première étape du débogage.
Ne pas avoir de sortie à l'écran ne signifie pas que le destructeur n'est pas appelé: le ouptut pourrait être capturé en utilisant output_buffering (peut-être que Lime le fait, pour pouvoir y travailler?), et non répercuté à la fin du script, par exemple.
À des fins de test, vous pouvez essayer d'écrire dans un fichier, dans votre __destruct
, au lieu de simplement faire écho à du texte.
(Assurez-vous simplement que votre application/PHP a les privilèges requis pour écrire dans votre fichier de destination)
(J'ai déjà rencontré des situations où je ne verrais pas la sortie effectuée dans un destructeur - mais elle était en fait appelée)
Le __destruct
la méthode ne sera pas non plus appelée si le script s'exécute sur CLI et reçoit un SIGTERM (Ctrl+C)
Comme la PHP dit:
Le destructeur sera appelé même si l'exécution du script est arrêtée à l'aide de
exit()
. L'appel deexit()
dans un destructeur empêchera l'exécution des routines d'arrêt restantes.
Je sais que je suis un peu en retard pour la fête, mais pour les gens qui cherchent également à obtenir __destruct
à exécuter lorsque CTRL+C et/ou des erreurs fatales se produisent, vous pouvez essayer ceci (ci-dessous est un cas de test):
Index.php
<?php
// Setup CTRL+C and System kill message handler
// The only signal that cannot be caught is the SIGKILL (very hard kill)
declare(ticks = 1); // Required else it won't work.
pcntl_signal(SIGTERM, 'close'); // System kill (Unhappy Termination)
pcntl_signal(SIGINT, 'close'); // CTRL+C (Happy Termination)
// Shutdown functions will be executed even on fatal errors
register_shutdown_function('close');
function close($signal = null) // only pcntl_signal fills $signal so null is required
{
// Check if there was an fatal error (else code below isn't needed)
$err = error_get_last();
if(is_array($err))
{
foreach(array_keys($GLOBALS) as $key)
{
if(in_array($key, ['_GET', '_POST', '_COOKIE', '_FILES', '_SERVER', '_REQUEST', '_ENV', 'GLOBALS']))
continue;
// This will automatically call __destruct
unset($GLOBALS[$key]);
}
}
}
// Example
class blah
{
private $id = '';
public function __construct()
{
$this->id = uniqid();
// note this piece of code, doesn't work on windows!
exec('mkdir /tmp/test_'.$this->id);
}
public function __destruct()
{
// note this piece of code, doesn't work on windows!
exec('rm /tmp/test_'.$this->id.' -R');
}
}
// Test
$a = new blah();
$b = new blah();
$c = new blah();
$d = new blah();
$e = new blah();
$f = new blah();
$g = new blah();
$h = new blah();
$i = new blah();
$j = new blah();
$k = new blah();
$l = new blah();
$m = new blah();
$n = new blah();
$o = new blah();
$p = new blah();
$q = new blah();
$r = new blah();
$s = new blah();
$t = new blah();
$u = new blah();
$v = new blah();
$w = new blah();
$x = new blah();
$y = new blah();
$z = new blah();
// The script that causes an fatal error
require_once(__DIR__.'/test.php');
Test.php
<?php
// this will create a parse (E_PARSE) error.
asdsaddsaadsasd
Remarque: l'appel à exit ou le lancement d'exceptions dans les destructeurs ou les fonctions d'arrêt entraînera la fin immédiate du script.