Могу ли я доверять вызову метода PHP __destruct ()?

В PHP5 гарантированно ли вызывается метод __destruct () для каждого экземпляра объекта? Могут ли исключения в программе предотвратить это?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
43
0
33 999
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Деструктор будет вызван, когда все ссылки будут освобождены или когда сценарий завершится. Я предполагаю, что это означает, что сценарий завершается правильно. Я бы сказал, что критические исключения не гарантируют вызов деструктора.

Документация PHP немного тонок, но он говорит, что исключения в деструкторе вызовут проблемы.

Могу сказать, что исключения во время завершения работы могут вызвать ошибки сегментации.

KingCrunch 31.12.2011 03:16

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

Jason Cohen 29.05.2013 19:17

Извините, я не могу представить ваш пример. Не могли бы вы уточнить? @JasonCohen

revo 18.06.2016 14:01

Если вам нужно, чтобы деструктор вызывал даже в случае фатальной ошибки php, зарегистрируйте его как обработчик завершения работы в конструкторе: public function __construct() { register_shutdown_function(array($this, '__destruct')); }. Стоимость этого решения заключается в том, что ссылка на объект (и сам объект) существует до конца выполнения скрипта php. Тем не менее, есть случаи, когда они того стоят - например, удаление огромных файлов tmp в деструкторе.

Mojo 30.06.2016 12:20

Также стоит упомянуть, что в случае подкласса, у которого есть собственный деструктор, автоматически вызывается родительский деструктор нет.

Вы должны явно вызвать родитель :: __ destruct () из метода подкласса __destruct (), если родительский класс выполняет любую требуемую очистку.

Я считаю, что это верно только тогда, когда дочерний класс реализует свой собственный __destruct (), иначе будет вызван родительский __destruct ().

Geoff 30.09.2008 08:03

В настоящее время существует ошибка с циклическими ссылками, из-за которой неявно вызывается метод деструкции. http://bugs.php.net/bug.php?id=33595 Это должно быть исправлено в 5.3.

Он был закрыт в 5.3.

robsch 13.02.2017 18:43

По моему опыту, деструкторы всегда будут вызываться в PHP 5.3, но имейте в виду, что если какой-то фрагмент кода вызывает exit () или если возникает фатальная ошибка, PHP вызовет деструкторы в «любом» порядке (я думаю, что фактический порядок - порядок в memory или порядок, в котором память была зарезервирована для объектов (на практике этот порядок почти всегда проблематичен). В документации PHP это называется «последовательностью выключения».

PHP-документация деструкторов говорит:

PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++. The destructor method will be called as soon as there are no other references to a particular object, or in any order during the shutdown sequence.

В результате, если у вас есть класс 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.

Обоснование PHP: «Я придерживаюсь текущей реализации, потому что считаю ее лучшим компромиссом. --Andi». Источник: mail-archive.com/[email protected]/msg06393.html

Mikko Rantalainen 28.11.2011 16:14

В основном есть две группы кодировщиков: (1) кодеры, использующие глобальные переменные в деструкторах и (2) кодеры, которые не используют глобальные переменные в деструкторах И правильно размечают зависимости, используя объектные ссылки на зависимые объекты. Поскольку PHP пытается нацелиться на нижнюю часть, он обслуживает (1) над (2). В группе (2) остался некорректно работающий код и нет официального способа решения проблемы.

Mikko Rantalainen 28.11.2011 16:19

См. Также: stackoverflow.com/questions/2385047/…

Mikko Rantalainen 07.05.2013 15:52

Используйте функцию выключения, если хотите точно: register_shutdown_function ()

Из документации: «Можно сделать несколько вызовов register_shutdown_function (), и каждый из них будет вызываться в том же порядке, в котором они были зарегистрированы. Если вы вызовете exit () в одной зарегистрированной функции выключения, обработка полностью прекратится, и никакое другое зарегистрированное выключение не будет функции будут вызываться ". Нет гарантии, что функция выключения ваш будет вызвана, если какая-то другая функция выключения будет запущена раньше вашей.

Mikko Rantalainen 02.09.2013 13:23

Другие вопросы по теме