Sequential execution of _ destruct and register_shutdown_function in php

Source: Internet
Author: User

Sequential execution of _ destruct and register_shutdown_function in php

According to the php manual.

_ Destruct is

The Destructor is executed when all references to an object are deleted or when the object is explicitly destroyed.

While register_shutdown_function is

Registers a callback to be executed after script execution finishes or exit () is called. Register a callback function that is executed after the script is run or when exit () is called.

Literally speaking, __destruct is at the object level, while register_shutdown_function is at the script level. It is supposed that register_shutdown_function has a higher level and the registered function should be executed at the end. To prove our guesses, we have written a script:

 

The Code is as follows:


Register_shutdown_function (function () {echo 'global ';});
Class {
Public function _ construct (){
}
Public function _ destruct ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
}
New;

 

Execution result:

 

The Code is as follows:


A: :__ destruct
Global

 

It fully proves our conjecture that it is executed in the order of Object-> script.

But what if we have registered register_shutdown_function in the object? Is it in the same order ?!

 

The Code is as follows:


Class {
Public function _ construct (){
Register_shutdown_function (function () {echo 'local', '<br/> ';});
}
Public function _ destruct ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
}
New;

 

Result:

 

Copy the Code as follows:


Local
A: :__ destruct

 

We can see that register_shutdown_function is called first, and finally the _ destruct of the execution object. This indicates that the function registered by register_shutdown_function is treated as a method in the class ?! Unknown, this may need to view the php source code for parsing.

We can expand the scope to view the situation:

 

The Code is as follows:


Register_shutdown_function (function () {echo 'global', '<br/> ';});
Class {
Public function _ construct (){
Register_shutdown_function (array ($ this, 'op '));
}
Public function _ destruct ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
Public function op ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
}
Class B {
Public function _ construct ()
{
Register_shutdown_function (array ($ this, 'op '));
$ Obj = new;
}
Public function _ destruct ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
Public function op ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
}
$ B = new B;

 

We register a register_shutdown_function globally, register another function in class AB, and the class also has the destructor. What is the final running result?

 

The Code is as follows:


Global
B: op
A: op
A: :__ destruct
B: :__ destruct

 

The result completely subverts our imagination. The register_shutdown_function is first executed no matter whether it is registered in the class or globally, and the execution sequence in the class is the order in which they are registered. If we study the global register_shutdown_function both in front and in the back, it seems that the result is returned, that is, register_shutdown_function is executed first than _ destruct, the global register_shutdown_function is executed before the register_shutdown_function registered in the class.

I cannot accept this result. According to this conclusion, it is hard to say that the script can be executed again after it is completed _ destruct ?! Therefore, I will continue to verify this conclusion-remove the Registry register_shutdown_function in the class and keep the global register_shutdown_function:

 

The Code is as follows:


Class {
Public function _ destruct ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
}
Class B {
Public function _ construct ()
{
$ Obj = new;
}
Public function _ destruct ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
}
Register_shutdown_function (function () {echo 'global', '<br/> ';});

 

Output:

 

The Code is as follows:


A: :__ destruct
Global
B: :__ destruct

 

The result is confusing. The execution sequence of destructor A and B is unquestionable. Because Class A is definitely destroyed before class B when class A is called in Class B, but how can the global register_shutdown_function be executed in the middle of them ?! Confusing.

According to the manual parsing, The Destructor can also be executed when exit is called.

The Destructor will be called even when the exit () Termination script is used. Calling exit () in the Destructor will stop other close operations.

How can exit be called in a function?

 

The Code is as follows:


Class {
Public function _ construct (){
Register_shutdown_function (array ($ this, 'op '));
Exit;
}
Public function _ destruct ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
Public function op ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
}
Class B {
Public function _ construct ()
{
Register_shutdown_function (array ($ this, 'op '));
$ Obj = new;
}
Public function _ destruct ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
Public function op ()
{
Echo _ class __, ':' ,__ function __, '<br/> ';
}
}
Register_shutdown_function (function () {echo 'global', '<br/> ';});
$ B = new B;

 

Output:

 

The Code is as follows:


Global
B: op
A: op
B: :__ destruct
A: :__ destruct

 

This order is similar to the third example above. What is different and incredible is that Class B destructor are executed before Class, will all references to Class A be destroyed after Class B is destroyed ?! Unknown.

Conclusion:
1. Try not to mix register_shutdown_function and _ destruct in the script. Their behavior is completely unpredictable.
1. Because the objects are being referenced by each other, we cannot determine when the objects will be destroyed. When the content needs to be output in order, the content should not be placed in the Destructor _ destruct;
2. Try not to register register_shutdown_function in the class, because its order is difficult to predict (the function is registered only when this object is called), and _ destruct can replace register_shutdown_function;
3. If you need to execute relevant actions when the script exits, it is best to register register_shutdown_function at the beginning of the script and put all the actions in one function.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.