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

PHP 異常處理機制:頂層異常處理器 set_exception_handler 完整指南

     編輯:PHP 綜合知識

在 PHP 中,頂層異常處理器 是當程式碼拋出異常但未被任何 try-catch 區塊捕獲時,最後的防線。透過 set_exception_handler() 註冊自訂函式,可統一記錄錯誤日誌、顯示友善錯誤頁面,避免暴露敏感堆疊資訊。

核心概念

  • 觸發時機:只有當異常「未被捕獲」時才會呼叫頂層處理器。
  • 預設行為:若未註冊,PHP 內建處理器會輸出 Fatal error: Uncaught Exception... 並終止腳本。
  • 註冊方式:set_exception_handler('myHandler');,處理器函式需接受一個 Exception 物件參數。

程式碼範例:基本用法

<?php
// 註冊頂層異常處理器
set_exception_handler('myTopHandler');

function myTopHandler($exception) {
    // 實務上應記錄至日誌檔,而非直接 echo
    echo "【頂層處理器捕獲】代碼:{$exception->getCode()} | 訊息:{$exception->getMessage()} | 檔案:{$exception->getFile()} 第 {$exception->getLine()} 行";
}

// 測試:拋出未被捕獲的異常
throw new Exception("這是一個刻意拋出的測試異常", 1001);
?>

進階範例:結合 try-catch 與重新拋出

<?php
set_exception_handler('globalHandler');

function globalHandler($e) {
    error_log("[GLOBAL] " . $e->getMessage()); // 寫入錯誤日誌
    http_response_code(500);
    include __DIR__ . '/templates/500.php';    // 顯示友善錯誤頁
    exit;
}

function riskyOperation($input) {
    if ($input === 'hello') {
        throw new Exception("禁止輸入 'hello'", 400);
    }
    return "處理成功:" . $input;
}

try {
    // 假設這裡呼叫深層函式庫,可能拋出各種異常
    echo riskyOperation("hello"); // 觸發異常
} catch (Exception $e) {
    // 區域性處理:記錄、轉型、或判斷是否需重新拋出
    if ($e->getCode() === 400) {
        // 業務邏輯錯誤,直接顯示給使用者
        echo "操作失敗:" . $e->getMessage();
    } else {
        // 系統級錯誤,拋給頂層處理器統一處理
        throw $e;
    }
}
?>

重要陷阱:並非所有錯誤都是 Exception

PHP 早期版本的錯誤(如 Warning、Notice、除以零)不會拋出 Exception,而是觸發傳統錯誤處理機制。因此:

<?php
try {
    $result = 10 / 0; // 產生 Warning,非 Exception
} catch (Exception $e) {
    echo "永遠不會執行到這裡";
}
// 輸出:Warning: Division by zero ...
?>

解決方案:PHP 7+ 可用 set_error_handler() 將錯誤轉為 ErrorException;或直接升級至 PHP 7/8,大多數嚴重錯誤已改為拋出 Error(實作 Throwable 介面),可統一捕獲。

最佳實踐總結

  1. 生產環境務必註冊頂層處理器,避免堆疊追蹤洩露伺服器結構。
  2. 處理器中不要拋出新異常,否則會導致致命錯誤。
  3. 區分「業務異常」(預期內,如驗證失敗)與「系統異常」(預期外,如資料庫連線失敗),前者在區域 catch 處理,後者拋給頂層。
  4. 搭配 register_shutdown_function() 捕獲致命錯誤(PHP 7 前)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved