一、PHP 錯誤處理
1. 開發與生產環境配置策略
| 階段 | error_reporting | display_errors | log_errors | error_log |
| 開發環境 | E_ALL | On | On | 指定文件或 syslog |
| 生產環境 | E_ALL & ~E_NOTICE & ~E_DEPRECATED | Off | On | 指定可寫文件路徑 |
2. 配置示例
<?php
// 開發環境建議
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/logs/php_error.log');
// 生產環境建議(通常在 php.ini 配置)
// error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
// display_errors = Off
// log_errors = On
// error_log = /var/log/php/error.log
?>
3. 常見錯誤級別常量
| 值 | 常量 | 說明 |
| 2 | E_WARNING | 非致命運行時警告,腳本繼續執行 |
| 8 | E_NOTICE | 運行時通知,潛在問題 |
| 256 | E_USER_ERROR | 用戶觸發的致命錯誤 |
| 512 | E_USER_WARNING | 用戶觸發的警告 |
| 1024 | E_USER_NOTICE | 用戶觸發的通知 |
| 4096 | E_RECOVERABLE_ERROR | 可捕獲的致命錯誤 |
| 8191 | E_ALL | 所有錯誤和警告 |
4. 獲取最後一個錯誤:error_get_last()
<?php
echo $undefined_var; // 觸發 Notice
print_r(error_get_last());
/* 輸出示例:
Array (
[type] => 8
[message] => Undefined variable: undefined_var
[file] => /path/to/script.php
[line] => 2
)
*/
?>
二、PHP 異常處理機制
1. 基礎語法
try {
// 可能拋出異常的代碼
} catch (ExceptionType $e) {
// 處理異常
} finally {
// PHP 5.5+ 支持,無論是否異常都會執行
}
2. 核心執行流程
try 塊中代碼正常執行 → 異常拋出 → 立即跳轉到匹配的 catch 塊 → catch 執行完畢 → 繼續執行 finally (如有) → 繼續後續代碼
- 若
try 無異常 → 正常執行完 → 執行 finally → 繼續後續代碼
3. 內置 Exception 類關鍵方法
getMessage():異常消息
getCode():異常代碼
getFile():發生文件
getLine():發生行號
getTrace():堆棧跟蹤數組
getTraceAsString():格式化堆棧字符串
4. 自定義異常類
<?php
class OpenFileException extends Exception {
// 可選:重寫構造函數
public function __construct($message = "", $code = 0, Exception $previous = null) {
parent::__construct($message, $code, $previous);
}
// 業務專用:異常恢復邏輯
public function recover() {
touch("tmp.txt");
return fopen("tmp.txt", "r");
}
}
// 使用示例
try {
$file = @fopen("tmp.txt", "r");
if (!$file) {
throw new OpenFileException("文件打開失敗", 1001);
}
} catch (OpenFileException $e) {
echo "捕獲異常: " . $e->getMessage() . "\n";
$file = $e->recover(); // 嘗試恢復
} catch (Exception $e) {
echo "其他異常: " . $e->getMessage() . "\n";
}
?>
5. 多異常捕獲實戰模式
<?php
class DemoException extends Exception { public function handle() { echo "處理 Demo 異常\n"; } }
class TestException extends Exception { public function handle() { echo "處理 Test 異常\n"; } }
class Service {
public function demo($flag = 0) { if ($flag) throw new DemoException("Demo 異常"); }
public function test($flag = 0) { if ($flag) throw new TestException("Test 異常"); }
}
try {
$svc = new Service();
$svc->demo(0);
$svc->test(1); // 拋出 TestException
echo "正常結束\n";
} catch (DemoException $e) {
$e->handle();
} catch (TestException $e) {
$e->handle();
} catch (Exception $e) {
echo "未知異常: " . $e->getMessage() . "\n";
} finally {
echo "清理資源 / 記錄日誌\n";
}
?>
三、最佳實踐建議
- 區分錯誤與異常: 錯誤多為系統級、不可預期;異常為業務邏輯可預期、可處理的偏離流程。
- 異常分層: 定義基礎業務異常基類,派生具體業務異常,便於分類捕獲。
- 不要吞沒異常:
catch 中至少記錄日誌,或重新拋出、轉換為更高層異常。
- 善用 finally: 釋放鎖、關閉連接、清理臨時資源。
- 生產環境關閉顯示: 通過錯誤處理器將異常轉為友好提示,詳細信息寫入日誌。