基礎語法:try-catch
<?php
$path = "D:\\in.txt";
try {
file_open($path);
} catch (Exception $e) {
echo $e->getMessage();
}
function file_open($path) {
if (!file_exists($path)) {
throw new Exception("檔案不存在", 1);
}
if (!fopen($path, "r")) {
throw new Exception("檔案無法開啟", 2);
}
}
?>
Exception 物件常用方法
| 方法 | 說明 |
getMessage() | 例外訊息 |
getCode() | 例外代碼 |
getFile() | 發生例外的檔案名 |
getLine() | 發生例外的行號 |
getTrace() | 回溯陣列 |
getTraceAsString() | 格式化回溯字串 |
完整資訊輸出範例
catch (Exception $e) {
echo "異常訊息:" . $e->getMessage() . "\n";
echo "異常代碼:" . $e->getCode() . "\n";
echo "檔案名:" . $e->getFile() . "\n";
echo "行號:" . $e->getLine() . "\n";
echo "回溯:\n" . $e->getTraceAsString();
}
自訂例外類別
class FileExistsException extends Exception {}
class FileOpenException extends Exception {}
try {
file_open($path);
} catch (FileExistsException $e) {
echo "程式發生異常:" . $e->getMessage() . "\n";
echo "請確認檔案位置。";
} catch (FileOpenException $e) {
echo "程式發生異常:" . $e->getMessage() . "\n";
echo "請確認檔案可讀性。";
} catch (Exception $e) {
echo "[未知異常] " . $e->getMessage();
}
function file_open($path) {
if (!file_exists($path)) {
throw new FileExistsException("檔案不存在", 1);
}
if (!fopen($path, "r")) {
throw new FileOpenException("檔案無法開啟", 2);
}
}
重拋例外
function file_open($path) {
try {
if (!file_exists($path)) {
throw new FileExistsException("檔案不存在", 1);
}
if (!fopen($path, "r")) {
throw new FileOpenException("檔案無法開啟", 2);
}
} catch (Exception $e) {
echo "file_open 內部捕獲異常\n";
throw $e; // 重拋給上層
}
}
PHP 7+ 新功能
Throwable 介面
Exception 與 Error 皆實作 Throwable,可統一捕獲:
try {
// 可能拋出 Exception 或 Error (如 TypeError)
} catch (Throwable $t) {
// 捕獲所有可拋出物件
}
多重捕獲
catch (FileExistsException | FileOpenException $e) {
// 同時處理兩種例外
}
最佳實務建議
- 不要吞沒例外:catch 後至少記錄日誌或重拋
- 具體優於通用:先捕獲具體例外,最後捕獲
Exception/Throwable
- 例外用於「異常」情況:預期會發生的錯誤(如驗證失敗)用回傳值/狀態碼處理
- 建立例外階層:
AppException → DatabaseException、ValidationException 等
- 提供足夠上下文:建構子帶入相關資料(ID、查詢語句等)
- 避免在建構子/解構子拋出例外:難以處理且可能導致資源洩漏
SPL 內建例外類別