首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 自定義錯誤處理器:優雅捕獲與記錄腳本錯誤

     編輯:PHP 相關知識

為什麼需要自定義錯誤處理?

默認情況下,PHP 腳本發生錯誤(如調用未定義函數)會直接在頁面輸出 Fatal error: Call to undefined function... 並終止執行。這不僅嚇壞用戶,還暴露了服務器路徑、代碼結構等敏感信息,構成安全隱患。PHP 提供了 set_error_handler() 機制,允許開發者攔截錯誤、記錄日誌、返回友好提示,甚至忽略特定錯誤繼續執行。

PHP 錯誤類型與報告級別

PHP 將錯誤分為三大類(由低到高):

  • Notice(通知):如使用未定義變量,不影響腳本運行。
  • Warning(警告):如 include() 失敗,腳本繼續執行。
  • Fatal Error(致命錯誤):如調用不存在的函數,腳本立即終止。

這些錯誤可在啟動、解析、編譯、運行階段發生。常用常量包括 E_NOTICE、E_WARNING、E_ERROR、E_ALL 等。

error_reporting() 控制顯示行為

error_reporting() 決定哪些錯誤會被顯示(而非是否發生)。三個典型示例:

示例 A:僅顯示警告與致命錯誤

<?php
error_reporting(E_WARNING | E_ERROR);
echo $undefinedVar;      // Notice,不顯示
callUndefFunc();         // Fatal Error,顯示並終止
?>

示例 B:關閉所有錯誤顯示

<?php
error_reporting(0);
echo $undefinedVar;      // 無輸出
callUndefFunc();         // 終止但無任何提示,用戶看到空白頁
?>

示例 C:顯示所有錯誤(開發環境推薦)

<?php
error_reporting(E_ALL);
echo $undefinedVar;      // Notice 顯示
callUndefFunc();         // Fatal Error 顯示
?>
關鍵點:error_reporting(0) 只隱藏輸出,不阻止致命錯誤導致腳本中斷。生產環境應配合 display_errors = Off、log_errors = On 將錯誤寫入日誌文件。

自定義錯誤處理器實戰

使用 set_error_handler() 註冊回調函數,可實現:

  • 記錄錯誤到數據庫/文件,包含堆疊追蹤、請求參數、用戶信息
  • 發送郵件/Slack 通知開發團隊
  • 返回 JSON 格式錯誤響應(API 專用)
  • 根據錯誤類型決定是否繼續執行(返回 true 表示已處理,腳本繼續)
<?php
function customErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
    // 忽略 error_reporting 設定外的錯誤
    if (!(error_reporting() & $errno)) return false;

    $log = "[".date('c')."] [$errno] $errstr in $errfile:$errline\n";
    error_log($log, 3, __DIR__.'/logs/php_errors.log'); // 寫入文件

    // 生產環境:返回友好頁面或 JSON
    if (php_sapi_name() !== 'cli') {
        http_response_code(500);
        echo '{"error":"系統繁忙,請稍後再試","code":500}';
        exit;
    }
    return true; // 不讓 PHP 內置處理器繼續
}

set_error_handler('customErrorHandler');
// 觸發測試
trigger_error('測試用戶級錯誤', E_USER_WARNING);
?>

進階:異常與錯誤統一處理

PHP 7+ 將多數致命錯誤轉為 Throwable 異常,可配合 set_exception_handler()、register_shutdown_function() 實現全棧捕獲:

set_exception_handler(function($e) {
    // 記錄異常...
    echo '系統錯誤,已記錄';
});
register_shutdown_function(function() {
    $err = error_get_last();
    if ($err && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR])) {
        // 捕獲致命錯誤
    }
});

最佳實踐清單

  1. 開發環境:error_reporting(E_ALL); ini_set('display_errors', 1);
  2. 生產環境:error_reporting(E_ALL); ini_set('display_errors', 0); ini_set('log_errors', 1); ini_set('error_log', '/var/log/php/error.log');
  3. 使用 try-catch 包裹業務邏輯,避免未捕獲異常導致 500。
  4. 敏感信息(密鑰、SQL)脫敏後再記錄日誌。
  5. 定期分析錯誤日誌,修復高頻問題。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved