首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 異常處理入門:try、throw、catch 基礎語法與實戰範例

     編輯:PHP 相關知識

PHP 異常處理入門:try、throw、catch 基礎語法與實戰範例

異常處理是現代 PHP 編寫健壯代碼的基石。本文從基礎語法切入,說明 try/throw/catch 機制、自訂異常類別、多重捕獲、finally 區塊與最佳實務。

一、核心三要素

  • try:包裹可能拋出異常的代碼區塊。
  • throw:主動拋出異常物件 (throw new Exception($message, $code))。
  • catch:捕獲異常並處理,可指定捕獲類型。

二、基本範例

<?php
function checkNumber(int $number): bool {
    if ($number > 1) {
        throw new Exception("數值必須 ≤ 1", 400); // 拋出異常
    }
    return true;
}

try {
    checkNumber(2); // 觸發異常
    echo "檢查通過\n"; // 不會執行
} catch (Exception $e) {
    echo "捕獲異常: {$e->getMessage()} (代碼: {$e->getCode()})\n";
    // 輸出: 捕獲異常: 數值必須 ≤ 1 (代碼: 400)
} finally {
    echo "finally 區塊總是執行\n";
}
?>

三、異常物件常用方法

方法說明
getMessage()異常訊息字串
getCode()異常代碼 (int)
getFile()拋出異常的檔案路徑
getLine()拋出異常的行號
getTrace()堆疊追蹤陣列
getTraceAsString()格式化堆疊字串
getPrevious()前一個異常 (巢狀異常)

四、多重 catch 與類型捕獲

<?php
class ValidationException extends Exception {}
class DatabaseException extends Exception {}

function process(array $data) {
    if (empty($data['email'])) throw new ValidationException('Email 必填');
    if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) throw new ValidationException('Email 格式錯誤');
    // 模擬資料庫錯誤
    if ($data['email'] === 'fail@db.com') throw new DatabaseException('連線失敗');
    return true;
}

try {
    process(['email' => 'invalid']);
} catch (ValidationException $e) {
    echo "驗證錯誤: {$e->getMessage()}\n";
} catch (DatabaseException $e) {
    echo "資料庫錯誤: {$e->getMessage()}\n";
} catch (Exception $e) {
    echo "其他錯誤: {$e->getMessage()}\n"; // 捕獲所有其他 Exception 子類
}
?>

規則:catch 依序匹配,子類別必須寫在父類別之前。

五、自訂異常類別最佳實務

<?php
abstract class AppException extends Exception {
    protected int $httpCode = 500;
    public function getHttpCode(): int { return $this->httpCode; }
}

class NotFoundException extends AppException {
    protected int $httpCode = 404;
    public function __construct(string $resource = 'Resource') {
        parent::__construct("{$resource} 不存在", 404);
    }
}

class UnauthorizedException extends AppException {
    protected int $httpCode = 401;
}
?>

好處:統一錯誤碼、HTTP 狀態碼映射、方便全域異常處理器識別類型。

六、全域異常處理器

<?php
set_exception_handler(function (Throwable $e) {
    // 記錄日誌
    error_log("Uncaught: {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}");

    // 根據環境決定輸出
    if (ini_get('display_errors')) {
        echo "<pre>{$e->getTraceAsString()}</pre>";
    } else {
        http_response_code($e instanceof AppException ? $e->getHttpCode() : 500);
        echo json_encode(['error' => $e->getMessage()]);
    }
});

// 也可捕獲 Fatal Error (PHP 7+)
register_shutdown_function(function () {
    $error = error_get_last();
    if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        throw new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']);
    }
});
?>

七、PHP 7+ Throwable 介面

PHP 7 引入 Throwable 介面,Exception 與 Error 皆實作之。catch (Throwable $e) 可同時捕獲例外與錯誤 (如 TypeError, ParseError)。

八、常見錯誤與避坑指南

  1. 用異常控制流程:異常僅用於「非預期/錯誤」情況,正常業務分支用 if/else。
  2. 吞沒異常:catch (Exception $e) {} 空白處理會隱藏 Bug,至少記錄日誌。
  3. 未捕獲的異常:會觸發全域處理器或顯示白屏/500,生產環境務必設定 set_exception_handler。
  4. 資源洩漏:使用 finally 關閉連線、釋放鎖、清理暫存檔。

九、實戰範例:API 統一回應格式

<?php
function apiResponse($data = null, string $message = '', int $code = 200): void {
    http_response_code($code);
    header('Content-Type: application/json');
    echo json_encode(compact('code', 'message', 'data'), JSON_UNESCAPED_UNICODE);
    exit;
}

try {
    $user = UserService::getById($_GET['id'] ?? 0);
    if (!$user) throw new NotFoundException('用戶');
    apiResponse($user);
} catch (NotFoundException $e) {
    apiResponse(null, $e->getMessage(), $e->getHttpCode());
} catch (ValidationException $e) {
    apiResponse(null, $e->getMessage(), 422);
} catch (Throwable $e) {
    apiResponse(null, '伺服器內部錯誤', 500);
}
?>

掌握異常處理機制,能讓你的 PHP 代碼更清晰、可維護、易於除錯。建立專案專屬的異常體系與全域處理器,是專業框架開發的標配。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved