優雅的錯誤處理是專業框架的標配。PHP 提供兩大核心機制捕獲不同類型錯誤:set_error_handler 處理可捕獲錯誤(Warning、Notice 等),register_shutdown_function 捕獲致命錯誤(Fatal Error)並統一輸出。
| 特性 | set_error_handler | register_shutdown_function |
|---|---|---|
| 觸發時機 | 運行時發生錯誤(非致命) | 腳本關閉時(正常結束或 Fatal Error) |
| 調用次數 | 每次錯誤觸發 | 每請求僅一次 |
| 可捕獲類型 | E_WARNING, E_NOTICE, E_DEPRECATED 等 | E_ERROR, E_PARSE, E_CORE_ERROR 等致命錯誤 |
| 獲取錯誤信息 | 回調參數直接提供 | 需用 error_get_last() 獲取最後錯誤 |
<?php
// 1. 註冊關閉處理器(捕獲 Fatal Error)
register_shutdown_function(function () {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
// 記錄日誌、渲染友好錯誤頁
log_error($error);
render_error_page($error);
}
});
// 2. 註冊錯誤處理器(捕獲 Warning/Notice)
set_error_handler(function ($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) return false; // 尊重 error_reporting 級別
// 開發環境顯示詳情,生產環境記錄日誌
if (DEBUG_MODE) {
throw new ErrorException($message, 0, $severity, $file, $line);
}
log_error(compact('severity', 'message', 'file', 'line'));
return true; // 阻止 PHP 內置處理器
});
PHP 7+ 將多數錯誤轉為 Error 異常(繼承 Throwable),可統一用 set_exception_handler 捕獲:
set_exception_handler(function (Throwable $e) {
log_error(['message' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
render_error_page($e);
});
HttpException(404/403/500)、ValidationException、BusinessException 等,便於差異化處理。錯誤捕獲不是「防止報錯」,而是「可控地面對錯誤」。掌握兩大處理器分工、善用 Throwable 統一異常體系,能構建健壯、可觀測的 PHP 應用。