許多開發者習慣在方法中 return new Exception(...),但這僅是回傳一個物件,**不會中斷程式流程**。正確做法是使用 throw 拋出異常:
throw new Exception('找不到指令檔案', 404);
throw 會立即中止目前腳本執行,並將 Exception 物件傳遞給最近的 catch 區塊或全域異常處理器,內建「失敗快速」的安全機制。
CommandManager以下展示如何結合 PHP 5 Reflection API,在載入指令類別時進行多層驗證:
<?php
// PHP 5
require_once('cmd_php5/Command.php');
class CommandManager {
private $cmdDir = 'cmd_php5';
function getCommandObject($cmd) {
$path = "{$this->cmdDir}/{$cmd}.php";
if (!file_exists($path)) {
throw new Exception("找不到指令檔案:$path");
}
require_once $path;
if (!class_exists($cmd)) {
throw new Exception("類別 $cmd 不存在");
}
$class = new ReflectionClass($cmd);
if (!$class->isSubclassOf(new ReflectionClass('Command'))) {
throw new Exception("$cmd 不是 Command 的子類別");
}
return new $cmd();
}
}
?>
若呼叫端未包裹 try-catch,PHP 會輸出 Fatal error: Uncaught exception... 並附上完整堆疊追蹤:
Fatal error: Uncaught exception 'Exception' with message '找不到指令檔案:cmd_php5/xrealcommand.php'
Stack trace:
#0 /home/xyz/BasicException.php(26): CommandManager->getCommandObject('xrealcommand')
#1 {main}
thrown in /home/xyz/BasicException.php on line 10
這比單純回傳 false 或錯誤碼更安全,因為強迫呼叫端正視錯誤,避免帶著無效資料繼續執行導致更嚴重後果。
class CommandNotFoundException extends Exception {}
class InvalidCommandException extends Exception {}
try {
$cmdObj = $manager->getCommandObject($input);
} catch (CommandNotFoundException $e) {
logError($e->getMessage());
show404();
} catch (InvalidCommandException $e) {
logError($e->getMessage());
show500();
} catch (Exception $e) {
logError($e->getMessage());
showGenericError();
}
Exception 建立領域專屬異常,方便分類捕獲。set_exception_handler() 統一記錄 Log、顯示友善錯誤頁,避免洩露堆疊細節給使用者。Error 與 Exception。throw 是 PHP 5 物件導向錯誤處理的核心,善用它能讓程式碼更清晰、更安全。結合 Reflection API 進行型別檢查、建立自訂異常階層、設定全域處理器,即可建構出企業級的健壯應用程式。