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

PHP 錯誤處理與異常機制全景指南:配置、捕獲、日誌、最佳實踐

     編輯:PHP 綜合知識

PHP 提供錯誤與異常雙重機制處理異常情況。錯誤屬於引擎級別(不可捕獲的致命錯誤除外),異常屬於應用級別(可捕獲、可控制流)。正確配置與使用是構建健壯應用的基石。

開發 vs 生產環境配置

指令開發環境生產環境說明
error_reportingE_ALLE_ALL & ~E_DEPRECATED & ~E_STRICT報告級別
display_errorsOnOff瀏覽器顯示
log_errorsOnOn寫入日誌
error_log/var/log/php_errors.log/var/log/php_errors.log日誌路徑
track_errorsOnOff$php_errormsg (已棄用)

運行時配置 (覆蓋 php.ini)

<?php
// 開發環境
ini_set('error_reporting', E_ALL);
ini_set('display_errors', '1');
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/logs/php_errors.log');

// 生產環境
ini_set('error_reporting', E_ALL & ~E_DEPRECATED & ~E_STRICT);
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', '/var/log/php/php_errors.log');
?>

錯誤級別常數

PHP 錯誤級別對照表

自定義錯誤處理器

<?php
function customErrorHandler(int $errno, string $errstr, string $errfile, int $errline, array $errcontext = []) {
    // 忽略未啟用的錯誤級別
    if (!(error_reporting() & $errno)) return false;
    
    $msg = "[{$errno}] {$errstr} in {$errfile}:{$errline}";
    error_log($msg . "\n", 3, '/var/log/php/custom_errors.log');
    
    // 開發環境顯示
    if (ini_get('display_errors')) {
        echo "
{$msg}
"; } return true; // 阻止內建處理器 } set_error_handler('customErrorHandler', E_ALL & ~E_DEPRECATED & ~E_STRICT); ?>

異常處理機制 (PHP 5+)

<?php
try {
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
    $stmt->execute([$id]);
    $user = $stmt->fetch();
    
    if (!$user) {
        throw new DomainException("用戶不存在: {$id}");
    }
} catch (PDOException $e) {
    error_log("DB Error: {$e->getMessage()}");
    throw new RuntimeException('服務暫時不可用', 503, $e);
} catch (DomainException $e) {
    http_response_code(404);
    echo $e->getMessage();
} finally {
    // 清理資源
}
?>

ErrorException:將錯誤轉為異常 (PHP 5+)

<?php
function errorToException(int $errno, string $errstr, string $errfile, int $errline) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler('errorToException', E_ALL);

try {
    $x = 1 / 0; // Warning: Division by zero → ErrorException
} catch (ErrorException $e) {
    echo "捕獲: {$e->getMessage()}";
}
?>

PHP 7+ 致命錯誤捕獲:Throwable 介面

<?php
// PHP 7+ 可捕獲 TypeError, ParseError, ArithmeticError 等
try {
    $fn = function(int $x) { return $x; };
    $fn('not int'); // TypeError
} catch (TypeError $e) {
    echo "類型錯誤: {$e->getMessage()}";
}

// 統一捕獲所有可拋出物件
try {
    // ...
} catch (Throwable $e) { // Error + Exception 共同父介面
    error_log("致命: {$e->getMessage()}\n{$e->getTraceAsString()}");
}
?>

獲取最後錯誤資訊

<?php
// error_get_last():最後發生的錯誤 (含致命錯誤)
register_shutdown_function(function() {
    $error = error_get_last();
    if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR])) {
        error_log("致命錯誤: {$error['message']} in {$error['file']}:{$error['line']}");
    }
});

// $php_errormsg (需 track_errors=On,PHP 8.0 棄用)
@$fp = fopen('nonexistent', 'r');
echo $php_errormsg; // 最後一個錯誤訊息
?>

最佳實踐總結

  1. 錯誤用於系統級:配置處理器記錄、不中斷流程 (除非致命)
  2. 異常用於業務級:throw new DomainException()、try-catch 控制流
  3. 永遠記錄日誌:生產環境 display_errors=Off、log_errors=On
  4. 異常分層:DomainException (業務)、RuntimeException (系統)、InvalidArgumentException (參數)
  5. 不要吞沒異常:至少記錄、或包裝重拋 throw new ...(prev: $e)
  6. 關閉 track_errors:PHP 8.0+ 已移除 $php_errormsg

錯誤與異常機制互補,配置得當能讓開發期快速定位、生產期靜默記錄、業務邏輯可控異常流,是專業 PHP 應用的標配。

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