生產環境通常關閉 display_errors,若發生 Fatal Error(如呼叫未定義類別、require 不存在檔案),使用者只會看到空白頁面,體驗極差。我們需要一個機制,在腳本異常終止前介入,輸出友善的錯誤訊息或記錄日誌。
register_shutdown_function 註冊的回調會在腳本執行結束(正常結束或因致命錯誤中止)前自動執行。搭配旗標變數即可判斷是否發生 Fatal Error。
<?php
$isNormalExit = false; // 全域旗標,預設為異常結束
function shutdownHandler(): void
{
global $isNormalExit;
if (!$isNormalExit) {
// 這裡可記錄錯誤日誌、發送告警、輸出友善頁面
// 注意:此階段無法再拋出例外或使用 die()/exit()
http_response_code(500);
echo '<h1>系統暫時無法服務,請稍後再試</h1>';
// error_log('Fatal Error 發生於 ' . date('Y-m-d H:i:s'));
}
}
register_shutdown_function('shutdownHandler');
// ---- 業務邏輯區 ----
// 模擬 Fatal Error:require 不存在的檔案、實例化未定義類別
// require './not_exist.php';
// $obj = new NotExistClass();
// 正常執行完畢,標記旗標
$isNormalExit = true;
function shutdownHandler(): void
{
global $isNormalExit;
if (!$isNormalExit) {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
// 記錄完整錯誤堆疊
error_log(sprintf(
"[FATAL] %s in %s on line %d",
$error['message'],
$error['file'],
$error['line']
));
}
// 輸出使用者友善頁面
include __DIR__ . '/templates/500.php';
}
}
ob_start() 控制輸出內容。