exit() 時執行。直觀認知:腳本級回調應晚於對象銷毀。但實測結果令人驚訝。
register_shutdown_function(function(){ echo 'global'; });
class A { public function __destruct(){ echo 'A::__destruct'; } }
new A;
輸出: A::__destruct → global ✅ 符合預期。
class A {
public function __construct(){
register_shutdown_function(function(){ echo 'local'; });
}
public function __destruct(){ echo 'A::__destruct'; }
}
new A;
輸出: local → A::__destruct ❌ shutdown 先於析構執行!
register_shutdown_function(function(){ echo 'global'; });
class A {
public function __construct(){ register_shutdown_function(array($this, 'op')); }
public function __destruct(){ echo 'A::__destruct'; }
public function op(){ echo 'A::op'; }
}
class B {
public function __construct(){ register_shutdown_function(array($this, 'op')); $obj = new A; }
public function __destruct(){ echo 'B::__destruct'; }
public function op(){ echo 'B::op'; }
}
$b = new B;
輸出: global → B::op → A::op → A::__destruct → B::__destruct
規律: 所有 register_shutdown_function(無論全局還是對象內)按註冊順序**優先執行**,隨後才按對象銷毀順序執行 __destruct。
class A { public function __destruct(){ echo 'A::__destruct'; } }
class B { public function __construct(){ $obj = new A; } public function __destruct(){ echo 'B::__destruct'; } }
register_shutdown_function(function(){ echo 'global'; });
$b = new B;
輸出: A::__destruct → global → B::__destruct ❌ 全局 shutdown 插在兩個析構之間!
class A {
public function __construct(){ register_shutdown_function(array($this, 'op')); exit; }
public function __destruct(){ echo 'A::__destruct'; }
public function op(){ echo 'A::op'; }
}
class B {
public function __construct(){ register_shutdown_function(array($this, 'op')); $obj = new A; }
public function __destruct(){ echo 'B::__destruct'; }
public function op(){ echo 'B::op'; }
}
register_shutdown_function(function(){ echo 'global'; });
$b = new B;
輸出: global → B::op → A::op → B::__destruct → A::__destruct ❌ B 析構先於 A,違背引用邏輯!
__destruct 順序輸出關鍵內容。__destruct 完全可替代其功能。register_shutdown_function,將所有清理邏輯封裝在**單一函數**中。歡迎指正補充,共同完善 PHP 生命週期認知。