Когда __destruct не будет вызываться в PHP?

class MyDestructableClass { function __construct() { print "\nIn constructor\n"; $this->name = "MyDestructableClass"; } function __destruct() { print "\nDestroying " . $this->name . "\n"; } } $obj = new MyDestructableClass(); 

Когда вышеупомянутый скрипт находится в сложной среде, __destruct не будет вызван при exit , но я не могу воспроизвести его легко. Кто-нибудь это заметил?

РЕДАКТИРОВАТЬ

Я размещу здесь весь материал, это тестовая среда symfony, а это означает, что вы можете легко воспроизвести его, если вы знакомы с каркасом:

 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('Ymd H:i:s',time())); $news->setUpdatedAt(date('Ymd H:i:s',time())); $news->save(); exit(); 

__destruct не будет вызываться:

  • Если exit вызывается в другом деструкторе
  • В зависимости от версии PHP: если вызывается exit в функции выключения, зарегистрированной с помощью register_shutdown_function
  • Если в коде есть фатальная ошибка
  • Если другой деструктор выдает исключение
  • Если вы попытаетесь обработать исключение в деструкторе (PHP> = 5.3.0)

Думаю, это все, о чем я могу думать сейчас

И что сказал Паскаль МАРТИН. Это первый шаг отладки.

Отсутствие вывода на экране не означает, что деструктор не вызывается: ouptut может быть захвачен с использованием output_buffering (может быть, лайм делает это, чтобы работать на нем?) , А не эхом, когда заканчивается скрипт, например ,

Для целей тестирования вы можете попробовать записать файл в свой метод __destruct вместо того, чтобы просто повторять какой-либо текст.
(Просто убедитесь, что ваше приложение / PHP имеет необходимые права для записи в файл назначения)

(Я уже сталкивался с ситуациями, когда я не видел вывод, сделанный в деструкторе, но он был фактически вызван)

Метод __destruct также не будет вызываться, если скрипт запущен в CLI и получает SIGTERM ( Ctrl + C )

Как указано в документации PHP :

Деструктор будет вызываться, даже если выполнение сценария прекращается с помощью функции exit() . Вызов exit() в деструкторе предотвратит выполнение остальных процедур выключения.

Я знаю, что немного опаздываю на вечеринку, но для людей, которые также хотят получить __destruct который будет выполнен, когда возникают CTRL + C и / или Fatal ошибки, вы можете попробовать это (ниже тестовый пример):

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'); не <?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 

Примечание: вызовы exit или throwing исключений в деструкторах или функции выключения вызовут немедленное завершение работы скрипта.

Не знакомы с Доктриной, но проверьте одну точку: проверьте возможные исключения в __construct () / __ destruct (), они могут привести к фатальным ошибкам.