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

PHP 錯誤處理完全指南:從 die() 到自定義異常與日誌記錄

     編輯:PHP 相關知識

為什麼錯誤處理至關重要?

缺乏錯誤處理的代碼不僅不專業,更會暴露敏感路徑、資料庫結構等資訊,成為攻擊者的切入點。完善的錯誤處理能提升用戶體驗、保障系統安全、便於開發者排查問題。

第一層:基礎防禦 - die() 與條件判斷

最簡單的方式是在高風險操作前預判,失敗時輸出友善訊息並終止腳本。

<?php
// 檢查文件是否存在再打開
if (!file_exists('welcome.txt')) {
    die('檔案不存在:welcome.txt');
}
$file = fopen('welcome.txt', 'r');
?>

優點:簡單直接。缺點:只能處理預期錯誤,無法捕捉運行時異常;終止腳本過於粗暴,不利於資源釋出與優雅降級。

第二層:自定義錯誤處理器 - set_error_handler()

PHP 允許註冊自定義函數接管所有錯誤(除 E_ERROR、E_PARSE 等致命錯誤外),實現統一格式化、記錄、通知。

錯誤處理函數簽名

function customError(int $errno, string $errstr, string $errfile = '', int $errline = 0, array $errcontext = []) : void

參數對應:錯誤級別、錯誤訊息、發生文件、行號、當時變量上下文(慎用,可能包含敏感數據)。

常見錯誤級別常量

值常量說明
2E_WARNING非致命運行時警告,腳本繼續
8E_NOTICE運行時提示,潛在問題
256E_USER_ERROR用戶觸發的致命錯誤
512E_USER_WARNING用戶觸發的警告
1024E_USER_NOTICE用戶觸發的提示
4096E_RECOVERABLE_ERROR可捕獲的致命錯誤
8191E_ALL所有錯誤與警告

註冊與觸發範例

<?php
// 1. 定義處理器
function customError($errno, $errstr, $errfile, $errline) {
    $log = "[ERROR] [$errno] $errstr in $errfile:$errline";
    error_log($log, 3, __DIR__ . '/error.log'); // 寫入文件
    // 生產環境不直接輸出,改為友善頁面
    if (ENV_PRODUCTION) {
        include '500.html';
        exit;
    }
    echo "<b>$log</b><br>";
}

// 2. 註冊為預設處理器(處理所有級別)
set_error_handler('customError', E_ALL);

// 3. 手動觸發測試
$test = 2;
if ($test > 1) {
    trigger_error('數值必須 ≤ 1', E_USER_WARNING);
}
?>

第三層:錯誤日誌與郵件通知 - error_log()

關鍵錯誤(如資料庫連接失敗、支付回調異常)需即時通知運維人員。

function criticalErrorHandler($errno, $errstr) {
    $msg = "Critical: [$errno] $errstr";
    error_log($msg, 1, 'ops@example.com', 'From: system@example.com'); // 發送郵件
    error_log($msg, 3, '/var/log/php/critical.log'); // 同時落盤
    die('系統繁忙,請稍後再試');
}

set_error_handler('criticalErrorHandler', E_USER_ERROR | E_RECOVERABLE_ERROR);

現代 PHP 最佳實踐:異常與 Throwable

PHP 7+ 引入 Throwable 介面,Error 與 Exception 均實現該介面。建議採用 try-catch-finally 結構處理可預期的業務異常,配合 set_exception_handler() 捕獲未捕獲異常。

<?php
// 全局異常處理器
set_exception_handler(function (Throwable $e) {
    http_response_code(500);
    error_log($e->getMessage() . '\n' . $e->getTraceAsString(), 3, '/var/log/php/exception.log');
    // 生產環境返回通用錯誤頁
    include 'error_500.html';
});

// 業務代碼中拋出異常
function transfer($from, $to, $amount) {
    if ($amount <= 0) throw new InvalidArgumentException('金額必須大於 0');
    // ... 數據庫操作 ...
    if ($dbError) throw new RuntimeException('轉賬失敗:' . $dbError);
}

try {
    transfer(1, 2, 100);
} catch (InvalidArgumentException $e) {
    // 參數錯誤,返回 400
} catch (RuntimeException $e) {
    // 系統錯誤,記錄並返回 500
}

總結建議

  1. 開發環境:error_reporting(E_ALL); ini_set('display_errors', '1'); 全部顯示。
  2. 生產環境:display_errors=Off; log_errors=On; error_log=/var/log/php/error.log 隱藏細節,記錄日誌。
  3. 分層處理:預期業務錯誤用異常;系統級錯誤用錯誤處理器;致命錯誤用 register_shutdown_function() 最後防線。
  4. 敏感資訊過濾:日誌中務必脫敏密碼、Token、身份證號等。

建立規範的錯誤處理體系,是從「能跑通」邁向「工程級可維護」的關鍵一步。

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