PHP 7 前,Error(致命錯誤)與 Exception(異常)泾渭分明;PHP 7+ 引入 Throwable 接口統一兩者,但處理邏輯仍有本質區別。本文對比 Java 異常體系,梳理 PHP Error/Exception 分類、捕獲方式與最佳實踐。
Object → Throwable → Exception → RuntimeException | Error
→ Error
OutOfMemoryError),通常不可恢復,不建議捕獲。IOException)與 Unchecked(RuntimeException 子類,如 NullPointerException)。
Throwable → Error (Engine 錯誤: TypeError, ParseError, ArithmeticError...)
→ Exception (用戶代碼異常: LogicException, RuntimeException...)
<?php
if (mysql_connect('127.0.0.1', 'root', 'pass')) {
echo '連接成功';
// 其他業務...
} else {
echo '連接失敗';
return false;
}
?>
<?php
try {
$pdo = new PDO("mysql:host=127.0.0.1;dbname=test", "root", "pass");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 其他業務...
} catch (PDOException $e) {
error_log("DB連接失敗: " . $e->getMessage());
// 友好提示或重試邏輯
die("系統維護中,請稍後再試");
}
?>
異常優勢:統一錯誤入口、堆棧追蹤、可鏈式捕獲多種異常、關鍵資源在 finally 中釋放。
| 類型 | 常量 | 可否用戶處理 |
|---|---|---|
| E_ERROR | 致命運行錯誤 | 否(腳本終止) |
| E_WARNING | 非致命警告 | 是(set_error_handler) |
| E_NOTICE | 運行通知 | 是 |
| E_USER_ERROR | 用戶觸發致命錯誤 | 是(trigger_error) |
| E_USER_WARNING | 用戶觸發警告 | 是 |
| E_USER_NOTICE | 用戶觸發通知 | 是 |
PHP 5 中 set_error_handler() 可攔截非致命錯誤,但無法捕獲 E_ERROR;set_exception_handler() 捕獲未處理異常。
| 維度 | Error (PHP 7+) | Exception |
|---|---|---|
| 來源 | 引擎/核心 | 用戶代碼/擴展 |
| 語義 | Bug、環境故障 | 業務邏輯異常流 |
| 處理策略 | 修復代碼、監控告警 | try-catch 處理、降級、重試 |
| 可恢復性 | 通常不可恢復 | 可恢復/可降級 |
| 繼承關係 | 實現 Throwable | 實現 Throwable |
display_errors,啟用 log_errors,Error 通過監控系統告警。Exception 或 \RuntimeException),避免直接拋擲基類。try-catch-finally 管理資源(連接、鎖、文件句柄)。set_exception_handler() 記錄未捕獲異常並返回友好頁面。Error 或 Throwable 基類(除非頂層日誌記錄),以免掩蓋 Bug。