国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > PHP > 正文

php中__destruct與register_shutdown_function執(zhí)行的先后順序問題

2024-05-04 23:26:10
字體:
來源:轉載
供稿:網(wǎng)友
這篇文章主要介紹了php中__destruct與register_shutdown_function執(zhí)行的先后順序問題,需要的朋友可以參考下
 
 

根據(jù)php手冊的解析。

__destruct是

析構函數(shù)會在到某個對象的所有引用都被刪除或者當對象被顯式銷毀時執(zhí)行。

register_shutdown_function

Registers a callback to be executed after script execution finishes or exit() is called. 注冊一個回調函數(shù),此函數(shù)在腳本運行完畢或調用exit()時執(zhí)行。

從字面上理解,__destruct是對象層面的,而register_shutdown_function是整個腳本層面的,理應register_shutdown_function的級別更高,其所注冊的函數(shù)也應最后執(zhí)行。為證實我們的猜測,我們寫一段腳本:

 

復制代碼代碼如下:

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

 

執(zhí)行結果:

 

復制代碼代碼如下:

A::__destruct 
global

 

完全證實了我們的猜測,它按照對象->腳本的順序被執(zhí)行了。

但如果我們在對象中注冊了register_shutdown_function呢?它還是一樣的順序嗎?!

 

復制代碼代碼如下:

class A {
        public function __construct(){
            register_shutdown_function(function(){echo 'local', '<br/>';});
        }
        public function __destruct()
        {
            echo __class__,'::',__function__,'<br/>';
        }
    }
    new A;

 

結果:

 

復制代碼代碼如下:

local 
A::__destruct

 

可以看到register_shutdown_function先被調用了,最后才是執(zhí)行對象的__destruct。這表明register_shutdown_function注冊的函數(shù)被當作類中的一個方法?!不得而知,這可能需要查看php源代碼才能解析了。

我們可以擴大范圍查看情況:

 

復制代碼代碼如下:

register_shutdown_function(function(){echo 'global', '<br/>';});
    class A {
        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 A;
        }
        public function __destruct()
        {
            echo __class__,'::',__function__,'<br/>';
        }
        public function op()
        {
            echo __class__,'::',__function__,'<br/>';
        }
    }
    $b = new B;

 

我們在全局注冊一個register_shutdown_function函數(shù),在類AB中又各注冊了一個,而且類中分別還有析構方法。最后運行結果會怎樣呢?

 

復制代碼代碼如下:

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

 

結果完全顛覆了我們的想像,register_shutdown_function函數(shù)無論在類中注冊還是在全局注冊,它都是先被執(zhí)行,類中執(zhí)行的順序就是它們被注冊的先后順序。如果我們再仔細研究,全局的register_shutdown_function函數(shù)無論放在前面還是后面都是這個結果,事情似乎有了結果,那就是register_shutdown_function比__destruct先執(zhí)行,全局的register_shutdown_function函數(shù)又先于類中注冊的register_shutdown_function先執(zhí)行。

且慢,我無法接受這個結果,按照這樣的結論,難道說腳本已經(jīng)結束后還可以再執(zhí)行__destruct?!因此,我還要繼續(xù)驗證這個結論---去掉類中注冊register_shutdown_function,而保留全局register_shutdown_function:

 

復制代碼代碼如下:

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

 

輸出:

 

復制代碼代碼如下:

A::__destruct 
global 
B::__destruct

 

結果令人茫然,A、B兩個類的析構函數(shù)執(zhí)行順序無可質疑,因為B中調用了A,類A肯定比B先銷毀,但全局的register_shutdown_function函數(shù)又怎么夾在它們中間被執(zhí)行?!費解。

按照手冊的解析,析構函數(shù)也可在調用exit時執(zhí)行。

析構函數(shù)即使在使用 exit()終止腳本運行時也會被調用。在析構函數(shù)中調用 exit() 將會中止其余關閉操作的運行。

如果在函數(shù)中調用exit,它們又如何被調用的呢?

 

復制代碼代碼如下:

class A {
        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 A;
        }
        public function __destruct()
        {
            echo __class__,'::',__function__,'<br/>';
        }
        public function op()
        {
            echo __class__,'::',__function__,'<br/>';
        }
    }
    register_shutdown_function(function(){echo 'global', '<br/>';});
    $b = new B;

 

輸出:

 

復制代碼代碼如下:

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

 

這個順序與上述第三個例子相似,不同的且令人不可思議的是B類的析構函數(shù)先于類A執(zhí)行,難道銷毀B后類A的所有引用才被全部銷毀?!不得而知。

結論:
1、盡量不要在腳本中將register_shutdown_function與__destruct混搭使用,它們的行為完全不可預測。
1、因為對象在相互引用,因此我們無法測知對象幾時被銷毀,當需要按順序輸出內容時,不應把內容放在析構函數(shù)__destruct里;
2、盡量不要在類中注冊register_shutdown_function,因為它的順序難以預測(只有調用這個對象時才會注冊函數(shù)),而且__destruct完全可以代替register_shutdown_function;
3、如果需要在腳本退出時執(zhí)行相關動作,最好在腳本開始時注冊register_shutdown_function,并把所有動作放在一個函數(shù)里。
敬請大家指正。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 横峰县| 喜德县| 芦溪县| 苍梧县| 裕民县| 中牟县| 固镇县| 长春市| 嘉善县| 定西市| 绥中县| 光泽县| 陆丰市| 银川市| 马山县| 万荣县| 团风县| 京山县| 蒙城县| 铅山县| 南汇区| 本溪市| 迁安市| 二连浩特市| 潢川县| 大石桥市| 靖远县| 元阳县| 荆州市| 定日县| 五大连池市| 曲麻莱县| 松江区| 明水县| 安丘市| 鲁山县| 诏安县| 托克托县| 平远县| 西贡区| 无为县|