Php destructor behavior

im trying to understand php constructor and destructor behavior. Everything goes as expected with the constructor, but I am having problems so that the destructor does not work implicitly. Ive done all the reading on php.net and related sites, but I can not find the answer to this question.

If I have a simple class, then something like:

class test{ public function __construct(){ print "contructing<br>"; } public function __destruct(){ print "destroying<br>"; } } 

and I call it something like:

 $t = new test; 

it prints a constructor message. However, I expect that when the script ends and the page displays, the destructor should fire. Of course, this is not so.

If I call unset ($ t); when the scripts end, of course, the destructor fires, but is there any way to make it work implicitly?

thanks for any advice

+10
oop php destructor
source share
5 answers

This is pretty easy to verify.

 <?php class DestructTestDummy { protected $name; function __construct($name) { echo "Constructing $name\n"; $this->name = $name; } function __destruct() { echo "Destructing $this->name\n"; //exit; } } echo "Start script\n"; register_shutdown_function(function() { echo "Shutdown function\n"; //exit }); $a = new DestructTestDummy("Mr. Unset"); $b = new DestructTestDummy("Terminator 1"); $c = new DestructTestDummy("Terminator 2"); echo "Before unset\n"; unset($a); echo "After unset\n"; echo "Before func\n"; call_user_func(function() { $c = new DestructTestDummy("Mrs. Scopee"); }); echo "After func\n"; $b->__destruct(); exit("Exiting\n"); 

In PHP 5.5.12, this prints:

 Start script Constructing Mr. Unset Constructing Terminator 1 Constructing Terminator 2 Before unset Destructing Mr. Unset After unset Before func Constructing Mrs. Scopee Destructing Mrs. Scopee After func Destructing Terminator 1 Exiting Shutdown function Destructing Terminator 2 Destructing Terminator 1 

So, we see that the destructor is called when we explicitly delete the object, when it goes out of scope, and when the script ends.

+16
source share

The __destruct() magic function is executed when an object is deleted / destroyed (using unset ). It is not called during shutdown script. When the PHP script finishes executing, it clears the memory but does not delete the objects as such, therefore the __destruct() methods __destruct() not called.

Perhaps you are thinking of register_shutdown_function() , which runs when your PHP script completes.

 function shutdown() { // code here echo 'this will be called last'; } register_shutdown_function('shutdown'); 
+6
source share

I understand that destructors are automatically called for any remaining objects when the script ends.

If you look at the man page for constructors and destructors , it seems the only way to bypass the destructors completely is if you call exit() from the destructor of the object that is destroyed before the object in question.

Do you use exit() in any of your destructors? Are there even several objects in the script?

If it’s not so difficult, perhaps you can post the actual code, not the sample code that you have in your question. In addition to the typo in your sample constructor, this code should call both constuctor and the destructor for your test object.

+3
source share

The __destruct method of the class is called when all references to the object are not set.

for example

 $dummy = (object) new Class(); 

The destructor is called automatically if the dummy object is null or the script exits.

 unset($dummy); // or $dummy = null; //exit(); //also possible 

However, to call the destructor method, there are three important points in memory:

First, the desctructor method must be open, not protected, or closed.

Secondly, refrain from using internal and circular references. For example:

 class NewDemo { function __construct() { $this->foo = $this; } function __destruct() { // this method will never be called // and cause memory leaks // unset will not clear the internal reference } } 

The following will also not work:

 $a = new Class(); $b = new Class(); $a->pointer = $b; $b->pointer = $a; unset($a); // will not call destructor unset($b); // will not call destructor 

Thirdly, the decision whether destructors will be called after sending the output. Through

 gc_collect_cycles() 

You can determine whether all destructors are called before sending data to the user.

See http://php.net/manual/en/language.oop5.decon.php for sources and a detailed explanation of magic destruction methods with examples.

0
source share

The __destruct() method is useless. Better to do something like this:

 class MyClass { function __construct() { register_shutdown_function([ &$this, 'the_end_game' ]); } function the_end_game() { /* Your last part of code, save logs or what you want */ } } 
0
source share

All Articles