在PHP__destruct和register_shutdown_function执行顺序

根据PHP手册的解析。

__destruct是

当对对象的所有引用被删除或对象被显式销毁时,就会执行析构函数。

和register_shutdown_function是

在执行脚本完成或完成()之后执行的寄存器、A、回调函数注册一个回调函数。当脚本运行或调用到()时执行此函数。

从字面上看,__destruct是对象的水平,并register_shutdown_function是剧本整体水平。它应该是register_shutdown_function水平较高,其注册功能也应执行最后确认我们的猜测,我们写了一个剧本:

复制代码代码如下所示:

register_shutdown_function(function(){ echo'global;});

类{

公共功能__construct(){

}

公共功能__destruct()

{

回声__class__,'::',__function__,;

}

}

新的一个;



实施结果:

复制代码代码如下所示:

答::__destruct

全球的



完全证实了我们的怀疑,这是按照对象脚本的顺序执行的。

但如果我们注册register_shutdown_function的对象吗是相同的顺序吗!

复制代码代码如下所示:

类{

公共功能__construct(){

register_shutdown_function(function(){ echo'local '、';});

}

公共功能__destruct()

{

回声__class__,'::',__function__,;

}

}

新的一个;



结果uff1a

复制代码代码如下所示:

局部

答::__destruct



你可以看到,register_shutdown_function就是第一,最后就是执行对象的__destruct。这表明register_shutdown_function注册函数是在类的方法。它不知道,这可能需要一个视图的PHP源代码解析。

我们可以扩大视野:

复制代码代码如下所示:

register_shutdown_function(function(){ echo'global '、';});

类{

公共功能__construct(){

register_shutdown_function(阵列($,'op '));

}

公共功能__destruct()

{

回声__class__,'::',__function__,;

}

公共职能部门()

{

回声__class__,'::',__function__,;

}

}

B类{

公共功能__construct()

{

register_shutdown_function(阵列($,'op '));

$ obj =新一;

}

公共功能__destruct()

{

回声__class__,'::',__function__,;

}

公共职能部门()

{

回声__class__,'::',__function__,;

}

}

新的b;



我们登记了register_shutdown_function功能在全球范围内,我们登记在AB类,有一个分析的方法分别在上课。操作的最终结果是什么

复制代码代码如下所示:

全球的

B:OP

答:OP

答::__destruct

B::__destruct



结果完全颠覆了我们的想象。的register_shutdown_function函数是在类或在全球登记首先执行。班里的秩序是他们注册的顺序。如果我们仔细研究,register_shutdown_function全球功能在前面或后面的都是这个结果,事情似乎有了结果,__destruct实施之前,register_shutdown_function,的register_shutdown_function函数和全局注册类register_shutdown_function实施之前。

等一下,我不能接受这个结果,根据得出的结论,有人说,剧本也可以__destruct结束后执行!所以,我会继续验证这一结论,删除注册register_shutdown_function在课堂上,并保持全球register_shutdown_function:

复制代码代码如下所示:

类{

公共功能__destruct()

{

回声__class__,'::',__function__,;

}

}

B类{

公共功能__construct()

{

$ obj =新一;

}

公共功能__destruct()

{

回声__class__,'::',__function__,;

}

}

register_shutdown_function(function(){ echo'global '、';});



输出:

复制代码代码如下所示:

答::__destruct

全球的

B::__destruct



结果很令人困惑。对两类A和B的析构函数的执行顺序是不容质疑的,因为一个叫B,和类必须先摧毁比B,但如何在全球register_shutdown_function功能是否被夹在他们之间吗令人费解的。

根据手册的解析,也可以在退出时调用析构函数。

即使在退出()终止脚本时,析构函数也被调用。

如果在函数中调用退出,如何调用它们

复制代码代码如下所示:

类{

公共功能__construct(){

register_shutdown_function(阵列($,'op '));

出口;

}

公共功能__destruct()

{

回声__class__,'::',__function__,;

}

公共职能部门()

{

回声__class__,'::',__function__,;

}

}

B类{

公共功能__construct()

{

register_shutdown_function(阵列($,'op '));

$ obj =新一;

}

公共功能__destruct()

{

回声__class__,'::',__function__,;

}

公共职能部门()

{

回声__class__,'::',__function__,;

}

}

register_shutdown_function(function(){ echo'global '、';});

新的b;



输出:

复制代码代码如下所示:

全球的

B:OP

答:OP

B::__destruct

答::__destruct



这个序列与上面的第三个例子相似。不同的和令人难以置信的是,B类的析构函数在类A之前执行,在销毁B之后,所有对A的引用都被销毁了吗可以没有它u3002

结论:

1。尽量不要混合register_shutdown_function在脚本__destruct,他们的行为是完全不可预知的。

1,因为对象互相引用,所以我们不知道对象什么时候被销毁。当我们需要输出的内容顺序,我们不应该把内容在析构函数__destruct。

2、尽量不登记register_shutdown_function类,因为它的秩序很难预测(仅调用函数调用这个对象时),和__destruct可以代替register_shutdown_function。

3、如果你需要执行相关的动作脚本时退出,最好是登记register_shutdown_function开头的脚本和发生在一个函数的所有行动。

请改正。