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

PHP 異常處理完整指南:try-catch、自訂異常、重拋與全域處理

     編輯:PHP 綜合知識

PHP 異常處理機制深度解析與最佳實務

PHP 5 引入物件導向異常處理,取代傳統錯誤回呼。正確使用 try-catch、自訂異常類別、異常鏈與全域處理器,能建構健壯、可維護的應用程式。本文透過六個遞進範例完整展示。

基礎範例 1:基本 try-catch 捕獲

<?php
function file_open($path) {
    if (!file_exists($path)) {
        throw new Exception("檔案不存在", 1);
    }
    if (!fopen($path, 'r')) {
        throw new Exception("檔案無法開啟", 2);
    }
    return true;
}

$path = 'D:\\in.txt';
try {
    file_open($path);
} catch (Exception $e) {
    echo "異常訊息: {$e->getMessage()}\n";
}
?>

範例 2:未捕獲異常會終止腳本

<?php
// 無 try-catch,異常會冒泡至全域,若無處理器則 Fatal Error
file_open('D:\\in.txt'); // 拋出異常
echo "這行不會執行"; // 程式已中止
?>

範例 3:設定全域異常處理器

<?php
function exception_handler($e) {
    echo "未捕獲異常: {$e->getMessage()}\n";
    // 記錄日誌、發送通知、顯示友善錯誤頁
}
set_exception_handler('exception_handler');

// 此處拋出的異常會被 exception_handler 捕獲
throw new Exception("測試全域處理器");
?>

範例 4:異常物件豐富資訊

<?php
try {
    file_open('D:\\in.txt');
} catch (Exception $e) {
    echo "訊息: {$e->getMessage()}\n";
    echo "代碼: {$e->getCode()}\n";
    echo "檔案: {$e->getFile()}\n";
    echo "行號: {$e->getLine()}\n";
    echo "堆疊追蹤:\n{$e->getTraceAsString()}\n";
}
?>

範例 5:自訂異常類別與多重 catch

依異常類型分流處理,符合開閉原則:

<?php
class FileNotFoundException extends Exception {}
class FileNotReadableException extends Exception {}

function file_open($path) {
    if (!file_exists($path)) throw new FileNotFoundException("檔案不存在: $path", 1);
    if (!is_readable($path)) throw new FileNotReadableException("檔案不可讀: $path", 2);
    return fopen($path, 'r');
}

try {
    file_open('D:\\in.txt');
} catch (FileNotFoundException $e) {
    echo "請確認檔案路徑: {$e->getMessage()}";
} catch (FileNotReadableException $e) {
    echo "請檢查檔案權限: {$e->getMessage()}";
} catch (Exception $e) {
    echo "未知錯誤: {$e->getMessage()}";
}
?>

範例 6:catch 順序錯誤示範 (父類別在前會攔截子類別)

<?php
// ❌ 錯誤順序:Exception 在前,子類別永不被捕獲
try { file_open('x'); }
catch (Exception $e) { echo "父類別"; }
catch (FileNotFoundException $e) { echo "子類別 - 永遠不會執行"; }

// ✅ 正確順序:具體在前,一般在後
try { file_open('x'); }
catch (FileNotFoundException $e) { echo "子類別"; }
catch (Exception $e) { echo "父類別"; }
?>

範例 7:異常重拋與包裝

底層捕獲後記錄日誌,再拋出原異常或包裝新異常:

<?php
function file_open($path) {
    try {
        if (!file_exists($path)) throw new FileNotFoundException("不存在", 1);
        if (!is_readable($path)) throw new FileNotReadableException("不可讀", 2);
    } catch (Exception $e) {
        error_log("file_open 內部錯誤: {$e->getMessage()}");
        throw $e; // 重拋原異常,保留堆疊
        // 或: throw new RuntimeException("開啟失敗", 0, $e); // 包裝 (PHP 5.3+)
    }
}
?>

異常處理黃金法則

原則說明
僅捕獲可處理的異常不知如何處理時勿捕獲,讓上層或全域處理器處理
catch 區塊保持精簡記錄、轉換、重拋;避免複雜業務邏輯
保留原始堆疊重拋用 throw $e;,包裝用 throw new NewEx(..., 0, $e)
自訂異常繼承 Exception不要繼承 Error (PHP 7 內部錯誤)
程式碼異常 vs 邏輯異常前者用 RuntimeException 系,後者用 LogicException 系
不要用異常控制流程預期情況 (如查無資料) 用回傳值/空物件,非真正錯誤

PHP 7+ Throwable 介面

PHP 7 引入 Throwable 介面,Exception 與 Error 皆實作之。捕獲所有錯誤:

try {
    // 可能拋出 Exception 或 Error (TypeError, ParseError 等)
} catch (Throwable $t) {
    // 處理所有可擲出物件
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved