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

PHP 異常處理最佳實踐:嵌套異常、SPL 內建類型與組件級 Marker Interface

     編輯:PHP 綜合知識

背景

PHP 5.3 引入兩大特性:嵌套異常(getPrevious())與 SPL 內建異常類型(13 種),配合組件級 Marker Interface,形成現代異常處理最佳實踐。

一、嵌套異常:保留原始錯誤上下文

場景:適配器模式封裝第三方庫/擴展(PDO、cURL、Soap),將其異常轉為統一的組件異常,同時保留原始異常。

class MyDb {
    private $pdo;
    public function execute(string $sql): int {
        try {
            return $this->pdo->exec($sql);
        } catch (PDOException $e) {
            throw new MyDbException('Query failed', 0, $e); // 第三參數為 previous
        }
    }
}

// 呼叫端
try {
    $db->execute($sql);
} catch (MyDbException $e) {
    echo "業務錯誤:{$e->getMessage()}\n";
    if ($prev = $e->getPrevious()) {
        echo "底層錯誤:{$prev->getMessage()} (Code: {$prev->getCode()})\n";
    }
}

二、SPL 13 種內建異常類型

分類異常類別繼承鏈適用場景
基類LogicExceptionException邏輯錯誤(預期可避免)
RuntimeExceptionException運行時錯誤(外部因素)
動態調用BadFunctionCallExceptionLogicExceptionis_callable() 失敗、__call() 不存在
BadMethodCallExceptionBadFunctionCallException方法不存在/不可呼叫
邏輯組DomainExceptionLogicException領域規則違反(如數值超出定義域)
InvalidArgumentExceptionLogicException參數型別/值不合法
LengthExceptionLogicException長度不符(陣列/字串)
OutOfRangeExceptionLogicException索引超出合法範圍
運行時組OutOfBoundsExceptionRuntimeException運行時索引越界(如陣列操作)
OverflowExceptionRuntimeException容器溢位(如堆疊滿)
RangeExceptionRuntimeException運行時數值超出範圍
UnderflowExceptionRuntimeException容器下溢(如堆疊空)
UnexpectedValueExceptionRuntimeException運行時遇到非預期值

邏輯 vs 運行時 判斷原則

  • 邏輯階段:物件建構、Setter、參數驗證 → 拋 LogicException 子類。
  • 運行階段:核心業務邏輯執行、外部 I/O、資源耗盡 → 拋 RuntimeException 子類。

三、組件級 Marker Interface 模式

目的:讓上層可針對「某組件的所有異常」捕獲,同時保留具體 SPL 類型語義。

namespace MyLib\Component;

interface Exception {} // Marker Interface

class InvalidArgumentException extends \InvalidArgumentException implements Exception {}
class RuntimeException       extends \RuntimeException       implements Exception {}

// 組件內部
class Processor {
    public function run($input) {
        if (!is_string($input)) {
            throw new InvalidArgumentException('Input must be string');
        }
        if ($this->externalServiceFails()) {
            throw new RuntimeException('Service unavailable');
        }
    }
}

捕獲策略

try {
    $proc->run($data);
} catch (MyLib\Component\InvalidArgumentException $e) {
    // 針對性處理
} catch (MyLib\Component\Exception $e) {
    // 組件通用處理
} catch (\InvalidArgumentException $e) {
    // SPL 類型處理
} catch (\Exception $e) {
    // 最後防線
}

四、最佳實踐檢查清單

  1. 所有公開 API 拋出具體 SPL 異常,而非通用 Exception。
  2. 封裝第三方異常時,務必傳入 $previous。
  3. 每個組件/模組定義 Marker Interface Exception,所有內部異常實作它。
  4. 異常訊息面向開發者(英文、具體),面向用戶的錯誤由上層轉換。
  5. 避免在異常中包含敏感資料(密碼、Token)。
  6. 建立統一異常日誌格式:時間、請求 ID、異常類別、訊息、堆疊、Previous 鏈。

結語

善用嵌套異常保留因果鏈、SPL 類型語義化錯誤分類、Marker Interface 實現組件級捕獲,三者結合構建清晰、可維護、可擴展的異常處理體系。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved