Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I trust PHP __destruct() method to be called?

In PHP5, is the __destruct() method guaranteed to be called for each object instance? Can exceptions in the program prevent this from happening?

like image 421
Casey Watson Avatar asked Sep 30 '08 03:09

Casey Watson


People also ask

What is __ destruct in PHP?

PHP - The __destruct FunctionA destructor is called when the object is destructed or the script is stopped or exited. If you create a __destruct() function, PHP will automatically call this function at the end of the script. Notice that the destruct function starts with two underscores (__)!

What are the __ construct () and __ destruct () methods in a PHP class?

Example# __construct() is the most common magic method in PHP, because it is used to set up a class when it is initialized. The opposite of the __construct() method is the __destruct() method. This method is called when there are no more references to an object that you created or when you force its deletion.

How do you destruct a class in PHP?

An object is an instance of a class. Using the PHP unset() function, we can delete an object. So with the PHP unset() function, putting the object that we want to delete as the parameter to this function, we can delete this object.


4 Answers

It's also worth mentioning that, in the case of a subclass that has its own destructor, the parent destructor is not called automatically.

You have to explicitly call parent::__destruct() from the subclass __destruct() method if the parent class does any required cleanup.

like image 182
Mark Biek Avatar answered Oct 21 '22 15:10

Mark Biek


The destructor will be called when the all references are freed, or when the script terminates. I assume this means when the script terminates properly. I would say that critical exceptions would not guarantee the destructor to be called.

The PHP documentation is a little bit thin, but it does say that Exceptions in the destructor will cause issues.

like image 21
Geoff Avatar answered Oct 21 '22 17:10

Geoff


In my experience destructors will be always called in PHP 5.3, but be warned that if some piece of code calls exit() or if a fatal error occurs, PHP will call destructors in "any" order (I think the actual order is order in memory or the order the memory was reserved for the objects. In practice, this order is almost always problematic). This is referred as "shutdown sequence" in PHP documentation.

PHP documentation of destructors says:

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.

As a result if you have class X which holds a reference to Y, the destructor of X may be called AFTER the destructor of Y has already been called. Hopefully, the reference to Y was not that important... Officially this is not a bug because it has been documented.

However, it's very hard to workaround this issue because officially PHP provides no way to know if destructor is called normally (destructors are called in correct order) or destructors are called in "any" order where you cannot use data from referenced objects because those might have been already destroyed. One could workaround this lack of detection using debug_backtrace() and examining the stack. Lack of normal stack seems to imply "shutdown sequence" with PHP 5.3 but this, too, is undefined. If you have circular references, the destructors of those objects will not be called at all with PHP 5.2 or lesser and will be called in "any" order during "shutdown sequence" in PHP 5.3 or greater. For circular references, there does not exists a logically "correct" order so "any" order is good for those.

There are some exceptions (this is PHP after all):

  • if exit() is called in another destructor, any remaining destructors will not be called (http://php.net/manual/en/language.oop5.decon.php)
  • if FATAL error occurs anywhere (many possible causes, e.g. trying to throw an exception out from any other destructor could be one cause), any remaining destructors will not be called.

Of course, if the PHP engine hits segmentation fault or some other internal bug occurs, then all bets are off.

If you want to understand current implementation of "shutdown sequence", see https://stackoverflow.com/a/14101767. Note that this implementation may change in future PHP versions.

like image 28
Mikko Rantalainen Avatar answered Oct 21 '22 15:10

Mikko Rantalainen


There is a current bug with circular references that stops the destruct method being called implicitly. http://bugs.php.net/bug.php?id=33595 It should be fixed in 5.3

like image 10
MOdMac Avatar answered Oct 21 '22 17:10

MOdMac