| 屬性/方法 | 說明 |
getMessage() | 異常消息字串 |
getCode() | 異常代碼(int) |
getFile() | 拋出文件路徑 |
getLine() | 拋出行號 |
getTrace() | 回溯數組 |
getTraceAsString() | 格式化回溯字串 |
__toString() | 完整描述(含堆疊) |
3. 自定義異常類:擴展業務語義
class AppException extends Exception {
// 可新增業務屬性
protected $errorCode;
public function __construct($message, $code = 0, $previous = null) {
parent::__construct($message, $code, $previous);
$this->errorCode = $code;
}
public function getErrorCode() { return $this->errorCode; }
// 友好輸出
public function __toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message}\n" . $this->getTraceAsString();
}
}
// 使用
try {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new AppException("Invalid email: $email", 1001);
}
} catch (AppException $e) {
logError($e->getErrorCode(), $e->getMessage());
}
好處:業務碼統一、便於日誌分類、API 直接返回結構化錯誤碼。
4. 多異常捕獲與捕獲順序
try {
// 可能拋出 AppException、PDOException、TypeError 等
$pdo->query($sql);
validateInput($input);
} catch (AppException $e) { // 先捕獲具體業務異常
handleBizError($e);
} catch (PDOException $e) { // 再捕獲數據庫異常
handleDbError($e);
} catch (Throwable $e) { // 最後捕獲所有剩餘 (PHP 7+)
handleUnknownError($e);
}
- 子類異常必須寫在父類之前,否則被父類攔截。
- PHP 7 起
Throwable 為頂層接口,涵蓋 Exception 和 Error。
5. 重新拋出異常:轉換/豐富上下文
try {
$pdo->query($sql);
} catch (PDOException $e) {
// 記錄底層錯誤,拋出業務異常
error_log("DB Error: " . $e->getMessage());
throw new AppException("數據庫操作失敗", 500, $e); // $e 作為 previous 保留鏈
}
調用方捕獲 AppException 即可,無需知曉 PDO 細節,實現分層解耦。
6. 頂層異常處理器:最後防線
function globalExceptionHandler(Throwable $e) {
// 記錄完整堆疊
error_log("Uncaught: " . $e->getTraceAsString());
// 用戶友好頁面
if (php_sapi_name() !== 'cli') {
http_response_code(500);
include __DIR__ . '/templates/500.html';
}
}
set_exception_handler('globalExceptionHandler');
// 測試
throw new Exception('測試頂層處理'); // 會觸發 globalExceptionHandler
適用於框架入口、CLI 腳本、API 統一錯誤輸出。
7. PHP 7+ 新特性:Throwable、TypeError、ArgumentCountError
Throwable:統一接口,catch 所有可拋出對象。
TypeError:類型聲明不匹配(嚴格模式)。
ArgumentCountError:參數數量錯誤。
DivisionByZeroError、ParseError、AssertionError 等內置 Error 類。
8. 生產級異常處理策略清單
- 分層定義:
DomainException(業務邏輯)、InfrastructureException(外部依賴)、PresentationException(控制器/視圖)。
- 統一響應格式:API 返回
{code, message, data, trace_id},由中間件捕獲異常轉換。
- 日誌分級:
ERROR 記錄業務異常+堆疊,CRITICAL 記錄基礎設施異常並告警。
- 不吞沒異常:catch 後必須處理(記錄/轉換/重拋),禁止空 catch。
- 資源清理用 finally:關閉連接、釋放鎖、刷新緩衝區。
- 測試覆蓋:單元測試驗證異常拋出條件、類型、消息、代碼。
總結
異常不是「錯誤」,而是「預期外但可控的流程分支」。善用 try-catch-finally、自定義異常體系、頂層處理器,能將錯誤處理從「到處判斷返回碼」轉變為「集中、結構化、可維護」的工程實踐。
- 上一篇文章: PHP MySQLi 面向對象操作完整指南:連接、增刪改查、事務與預處理
- 下一篇文章: Laravel 入門第一課:Composer 安裝、項目創建、環境配置全流程
Copyright ©
程式碼之家 All Rights Reserved