По моему опыту, деструкторы всегда будут вызываться в PHP 5.3, но имейте в виду, что если какой-то фрагмент кода вызывает exit () или если возникает фатальная ошибка, PHP будет вызывать деструкторы в «любом» порядке (я думаю, что в действительности порядок это порядок в памяти или порядок, в котором память была зарезервирована для объектов. На практике этот порядок почти всегда проблематичен). В документации PHP это называется «последовательностью выключения».
PHP документация деструкторов говорит:
PHP 5 представляет концепцию деструктора, аналогичную концепции других объектно-ориентированных языков, таких как C ++. Метод деструктора будет вызываться, как только не будет никаких других ссылок на конкретный объект или в каком-либо порядке во время последовательности выключения.
В результате, если у вас есть класс X, который содержит ссылку на Y, деструктор X может называться ПОСЛЕ того, как деструктор Y уже был вызван. Надеемся, что ссылка на Y была не так важна ... Официально это не ошибка, потому что она была задокументирована.
Однако, очень трудно обойти эту проблему, потому что официально PHP не предоставляет способа узнать, вызывается ли деструктор нормально (деструкторы вызываются в правильном порядке) или деструкторы вызываются в «любом» порядке, когда вы не можете использовать данные из ссылочных объектов. потому что те, возможно, уже были уничтожены. Можно обойти это отсутствие обнаружения, используя debug_backtrace () и исследуя стек. Отсутствие нормального стека, по-видимому, подразумевает «последовательность выключения» в PHP 5.3, но это тоже не определено. Если у вас есть циклические ссылки, деструкторы этих объектов вообще не будут вызываться в PHP 5.2 или ниже и будут вызываться в «любом» порядке во время «последовательности выключения» в PHP 5.3 или выше. Для циклических ссылок не существует логически «правильного» порядка, поэтому «любой» порядок подходит для них.
Есть некоторые исключения (в конце концов, это PHP):
- если
exit()
вызывается в другом деструкторе, все остальные деструкторы не будут вызываться (http://php.net/manual/en/language.oop5.decon.php)
- если ошибка
FATAL
возникнет где-либо (множество возможных причин, например, попытка выбросить исключение из любого другого деструктора, может быть одной из причин), то любые оставшиеся деструкторы не будут вызваны.
Конечно, если движок PHP сталкивается с ошибкой сегментации или возникает какая-либо другая внутренняя ошибка, тогда все ставки выключены.
Если вы хотите понять текущую реализацию "последовательности выключения", см. https://stackoverflow.com/a/14101767. Обратите внимание, что эта реализация может измениться в будущих версиях PHP.