PHP 错误处理完整指南
                           
天天向上
发布: 2025-03-21 00:05:30

原创
296 人浏览过

PHP 提供了多种错误处理机制,确保在应用程序发生错误时,能够正确地 捕获、记录、显示 并采取适当的处理措施。本文将介绍 PHP 错误处理的完整方案,包括 错误级别、错误日志、异常处理、错误处理函数 等内容。


1. PHP 错误类型(错误级别)

PHP 具有多个错误级别,每种级别代表不同的严重程度。以下是常见的错误级别:

错误级别说明
E_ERROR致命错误,脚本终止执行
E_WARNING警告,不会终止脚本,但可能会导致问题
E_NOTICE通知,可能的代码逻辑错误
E_PARSE解析错误,通常由语法错误引起
E_DEPRECATED不推荐使用,表示某些函数或特性将被废弃
E_STRICT强制标准,建议改进代码以符合 PHP 规范
E_ALL所有错误(不包括 E_STRICT

可以使用 error_reporting() 设定 PHP 错误级别。例如:

error_reporting(E_ALL & ~E_NOTICE); // 报告所有错误,但忽略 NOTICE 级别

2. 显示错误与记录日志

(1) 显示错误

在开发环境下,通常需要显示错误信息,以便调试问题。可以使用 display_errors 设置:

ini_set('display_errors', 1);
error_reporting(E_ALL);

php.ini 中也可以配置:

display_errors = On
error_reporting = E_ALL

📌 生产环境(线上环境)应禁用错误显示,以防止泄露敏感信息

ini_set('display_errors', 0);

(2) 记录错误日志

在生产环境下,推荐将错误记录到日志文件,而不是直接显示在页面上:

ini_set('log_errors', 1);
ini_set('error_log', '/var/log/php_errors.log');
error_reporting(E_ALL);

php.ini 配置:

log_errors = On
error_log = /var/log/php_errors.log

3. 使用 try-catch 处理异常

PHP 提供了 try-catch 机制来捕获异常,确保应用程序不会因致命错误而崩溃。

示例:捕获异常

function divide($a, $b) {
    if ($b == 0) {
        throw new Exception("除数不能为零");
    }
    return $a / $b;
}

try {
    echo divide(10, 0);
} catch (Exception $e) {
    echo "捕获到异常: " . $e->getMessage();
}

多个 catch 处理不同异常

try {
    throw new RuntimeException("运行时异常");
} catch (InvalidArgumentException $e) {
    echo "参数异常: " . $e->getMessage();
} catch (RuntimeException $e) {
    echo "运行时异常: " . $e->getMessage();
} catch (Exception $e) {
    echo "通用异常: " . $e->getMessage();
}

4. 自定义错误处理

可以使用 set_error_handler() 定义自己的错误处理函数,将错误转换为异常,或者记录错误日志。

示例:自定义错误处理函数

function customErrorHandler($errno, $errstr, $errfile, $errline) {
    $logMessage = "错误级别: [$errno] $errstr - $errfile:$errline\n";
    error_log($logMessage, 3, "/var/log/php_custom_errors.log");

    if ($errno == E_USER_ERROR) {
        echo "致命错误,请联系管理员。";
        exit();
    }
    return true;
}

// 设置自定义错误处理函数
set_error_handler("customErrorHandler");

// 触发错误
echo $undefined_variable; // 触发 NOTICE
trigger_error("自定义警告", E_USER_WARNING);

5. 自定义异常处理

除了 set_error_handler(),还可以使用 set_exception_handler() 处理未捕获的异常。

示例:自定义异常处理

function customExceptionHandler($exception) {
    $errorMsg = "未捕获异常: " . $exception->getMessage() . "\n";
    error_log($errorMsg, 3, "/var/log/php_custom_exceptions.log");
    echo "系统错误,请稍后再试!";
}

// 设置自定义异常处理函数
set_exception_handler("customExceptionHandler");

// 触发异常
throw new Exception("数据库连接失败");

6. 终止脚本时执行(register_shutdown_function

PHP 提供 register_shutdown_function(),可以在脚本终止时执行特定代码。例如:

function shutdownHandler() {
    $error = error_get_last();
    if ($error && $error['type'] === E_ERROR) {
        error_log("致命错误: {$error['message']} in {$error['file']} on line {$error['line']}", 3, "/var/log/php_shutdown_errors.log");
        echo "系统发生错误,请稍后再试。";
    }
}

// 注册终止处理函数
register_shutdown_function("shutdownHandler");

用途:

  • 记录 致命错误E_ERROR)导致的脚本终止
  • 发送错误通知(如邮件、Slack 报警)

7. PHP7 及以上的错误处理

PHP 7 引入了 Error 类,使错误可以像异常一样被捕获:

try {
    nonExistentFunction(); // 调用不存在的函数
} catch (Error $e) {
    echo "捕获到错误: " . $e->getMessage();
}

这样,即使是致命错误,也不会直接终止脚本,而是可以进行适当的处理。


8. 结合日志记录(Monolog)

在复杂应用中,建议使用 Monolog 进行日志管理:

composer require monolog/monolog
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('app');
$log->pushHandler(new StreamHandler('/var/log/app.log', Logger::WARNING));

$log->warning('这是一条警告日志');
$log->error('这是一条错误日志');

📌 Monolog 支持 Slack、数据库等多种日志存储方式


9. 错误处理最佳实践

开发环境

  • display_errors = On
  • error_reporting = E_ALL
  • log_errors = On

生产环境

  • display_errors = Off
  • error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
  • log_errors = On(写入日志)

推荐

  • 使用 try-catch 处理异常
  • 配置 set_error_handler() 处理非致命错误
  • 配置 set_exception_handler() 处理未捕获异常
  • register_shutdown_function() 捕获 E_ERROR
  • 使用 Monolog 进行高级日志管理

总结

方案说明
try-catch捕获异常 (Exception)
set_error_handler()处理自定义错误
set_exception_handler()处理未捕获异常
register_shutdown_function()捕获致命错误 (E_ERROR)
error_log()记录错误日志
Monolog高级日志管理

这样可以 提升 PHP 应用的稳定性和安全性,避免因错误导致程序崩溃。更多详细内容请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *