The order of execution of __destruct and register_shutdown_function in php, destruct_PHP tutorial

WBOY
Release: 2016-07-13 10:16:57
Original
814 people have browsed it

The order of execution of __destruct and register_shutdown_function in php, destruct

According to the analysis of php manual.

__destruct is

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

and register_shutdown_function is

Registers a callback to be executed after script execution finishes or exit() is called.

Literally understood, __destruct is at the object level, while register_shutdown_function is at the entire script level. Register_shutdown_function should be of a higher level, and the functions it registers should also be executed last. To confirm our guess, we write a script:

Copy code The code is as follows:

register_shutdown_function(function(){echo 'global';});
class A {
         public function __construct(){
}
        public function __destruct()
           {
echo __class__,'::',__function__,'
';
}
}
new A;

Execution result:

Copy code The code is as follows:

A::__destruct
global

Completely confirmed our guess, it was executed in the order of object->script.

But what if we register register_shutdown_function in the object? Is it still the same order? !

Copy code The code is as follows:

class A {
        public function __construct(){
Register_shutdown_function(function(){echo 'local', '
';});
}
        public function __destruct()
           {
echo __class__,'::',__function__,'
';
}
}
new A;

Result:

Copy code The code is as follows:

local
A::__destruct

You 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? ! I don't know, this may require viewing the php source code to parse it.

We can expand the scope to see the situation:

Copy code The code is as follows:

register_shutdown_function(function(){echo 'global', '
';});
    class A {
        public function __construct(){
            register_shutdown_function(array($this, 'op'));
        }
        public function __destruct()
        {
            echo __class__,'::',__function__,'
';
        }
        public function op()
        {
            echo __class__,'::',__function__,'
';
        }
    }
    class B {
        public function __construct()
        {
            register_shutdown_function(array($this, 'op'));
            $obj = new A;
        }
        public function __destruct()
        {
            echo __class__,'::',__function__,'
';
        }
        public function op()
        {
            echo __class__,'::',__function__,'
';
        }
    }
    $b = new B;

我们在全局注册一个register_shutdown_function函数,在类AB中又各注册了一个,而且类中分别还有析构方法。最后运行结果会怎样呢?

复制代码 代码如下:

global
B::op
A::op
A::__destruct
B::__destruct

结果完全颠覆了我们的想像,register_shutdown_function函数无论在类中注册还是在全局注册,它都是先被执行,类中执行的顺序就是它们被注册的先后顺序。如果我们再仔细研究,全局的register_shutdown_function函数无论放在前面还是后面都是这个结果,事情似乎有了结果,那就是register_shutdown_function比__destruct先执行,全局的register_shutdown_function函数又先于类中注册的register_shutdown_function先执行。

且慢,我无法接受这个结果,按照这样的结论,难道说脚本已经结束后还可以再执行__destruct?!因此,我还要继续验证这个结论---去掉类中注册register_shutdown_function,而保留全局register_shutdown_function:

复制代码 代码如下:

class A {
        public function __destruct()
        {
            echo __class__,'::',__function__,'
';
        }
    }
    class B {
        public function __construct()
        {
            $obj = new A;
        }
        public function __destruct()
        {
            echo __class__,'::',__function__,'
';
        }
    }
    register_shutdown_function(function(){echo 'global', '
';});

输出:

复制代码 代码如下:

A::__destruct
global
B::__destruct

The results are confusing. There is no doubt about the execution order of the destructors of classes A and B. Because A is called in B, class A must be destroyed before B, but how can the global register_shutdown_function function be sandwiched between them? be executed? ! Puzzling.

According to the analysis of the manual, the destructor can also be executed when exit is called.

The destructor is called even when the script is terminated using exit(). Calling exit() in the destructor will abort the remaining shutdown operations.

If exit is called in a function, how are they called?

Copy code The code is as follows:

class A {
        public function __construct(){
​​​​​​register_shutdown_function(array($this, 'op'));
exit;
}
        public function __destruct()
           {
echo __class__,'::',__function__,'
';
}
        public function op()
           {
echo __class__,'::',__function__,'
';
}
}
class B {
        public function __construct()
           {
​​​​​​register_shutdown_function(array($this, 'op'));
               $obj = new A;
}
        public function __destruct()
           {
echo __class__,'::',__function__,'
';
}
        public function op()
           {
echo __class__,'::',__function__,'
';
}
}
Register_shutdown_function(function(){echo 'global', '
';});
$b = new B;

Output:

Copy code The code is as follows:

global
B::op
A::op
B::__destruct
A::__destruct

This sequence is similar to the third example above. What is different and incredible is that the destructor of class B is executed before class A. Is it true that all references to class A are destroyed only after B is destroyed? ! unknown.

Conclusion:
1. Try not to mix register_shutdown_function and __destruct in scripts. Their behavior is completely unpredictable.
1. Because objects refer to each other, we cannot know when the object 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 will only be registered when this object is called), and __destruct can completely replace register_shutdown_function;
3. If you need to perform relevant actions when the script exits, it is best to register register_shutdown_function at the beginning of the script and put all actions in a function.
Please correct me.

For the problem of php destructor __destruct()

The destructor is the code that is called when an object is destroyed.
When this object is used up, the statements in this function will be automatically executed.
Put the code to close the database here. That is, the database connection is closed when the object is destroyed.

Is the __destruct() destructor in PHP an empty method, or does it perform any work?

You can do some operations, such as closing files, closing databases, etc. For example, the word program is very stupid. It won't close by itself when you open a file. If you run it a few times and then open the task manager, you will see that there are many words in the process and you have to close it manually.

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/895116.htmlTechArticleThe order of execution of __destruct and register_shutdown_function in php, destruct is analyzed according to the php manual. __destruct is a destructor that deletes all references to an object...
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!