register_shutdown_function() 註冊的回調會在 PHP 腳本**正常結束**、**致命錯誤終止**、**執行逾時**或**用戶強制停止**時自動執行,是執行清理、記錄錯誤、釋放資源的最後防線。
register_shutdown_function(callable $callback, mixed ...$args): void
error_get_last() 取得最後發生的致命錯誤die()/exit() 仍會觸發 shutdown 函數<?php
header("Content-Type: text/html; charset=utf-8");
class Shutdown {
public function endScript() {
// 捕獲致命錯誤
if ($error = error_get_last()) {
echo "";
print_r($error);
echo "";
}
// 絕對路徑寫入檔案(shutdown 時工作目錄可能已變更)
file_put_contents(__DIR__ . '/error.txt', 'Script ended at ' . date('Y-m-d H:i:s'));
die('腳本結束');
}
}
register_shutdown_function([new Shutdown(), 'endScript']);
// 故意觸發致命錯誤
echo md6(); // 未定義函數
Fatal error: Call to undefined function md6() in ... on line 18
Array
(
[type] => 1
[message] => Call to undefined function md6()
[file] => ...
[line] => 18
)
腳本結束
檔案 error.txt 成功寫入。
| 場景 | 說明 | 處理重點 |
|---|---|---|
| 用戶強制停止(瀏覽器關閉/停止按鈕) | 連線中斷觸發 shutdown | 檢查 connection_aborted(),避免繼續耗時運算 |
| 程式異常終止/逾時 | 致命錯誤、max_execution_time 到期 | error_get_last() 記錄錯誤、釋放鎖/連線 |
| PHP 4 模擬解構函數 | 舊版專案相容 | 在 shutdown 中釋放資源、關閉連線 |
__DIR__、realpath())max_execution_time 限制,長時間清理可能被殺掉ignore_user_abort(true); // 忽略用戶斷線,繼續執行
set_time_limit(0); // 移除時間限制
register_shutdown_function(function() {
// 這裡的程式碼會在回應已發送給瀏覽器後繼續執行
// 適合:發送郵件、寫入日誌、異步任務觸發
file_put_contents(__DIR__.'/bg.log', 'Background task done');
});
掌握 register_shutdown_function,能在 PHP 腳本生命週期的終點建立可靠的清理與監控機制。