跳至内容

错误与异常处理

这篇讲 PHP 中错误与异常的捕获和处理——从基础的 try/catch 到自定义异常、错误日志和开发/生产环境的区分策略。

错误 vs 异常

PHP 的报错机制分为两大类:

  • 错误(Error):引擎层面的问题——语法错误、类型错误、致命错误等。PHP 7 后大部分错误实现了 Throwable 接口,可以被捕获。
  • 异常(Exception):应用层面的问题——业务逻辑不符合预期时主动抛出,由开发者控制和处理。

try / catch / finally

基本结构:

<?php
try {
    // 可能出错的代码
    $result = 10 / 0;
} catch (DivisionByZeroError $e) {
    echo "不能除以零:" . $e->getMessage();
} catch (Exception $e) {
    echo "发生异常:" . $e->getMessage();
} finally {
    // 无论是否出错都会执行——常用于清理资源
    echo "清理完成。";
}
?>
finally 块是可选的,但在需要确保资源被释放时(如关闭数据库连接、删除临时文件)非常有用。

抛出异常

当业务逻辑不满足条件时,使用 throw 主动抛出异常:

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

try {
    echo divide(10, 0);
} catch (InvalidArgumentException $e) {
    echo "参数错误:" . $e->getMessage();
}
?>

自定义异常

通过继承 Exception 创建语义更明确的异常类:

<?php
class UserNotFoundException extends Exception {
    public function __construct(string $userId) {
        parent::__construct("用户 {$userId} 未找到", 404);
    }
}

// 使用
throw new UserNotFoundException("user_123");
?>

全局异常处理器

set_exception_handler() 捕获未被 catch 的异常,避免用户看到白屏或 PHP 错误信息:

<?php
set_exception_handler(function (Throwable $e) {
    // 记录日志
    error_log("未捕获异常: " . $e->getMessage() . " in " . $e->getFile() . ":" . $e->getLine());

    // 向用户显示友好的错误页面
    http_response_code(500);
    echo "服务器内部错误,请稍后重试。";
});
?>

开发 vs 生产环境的错误策略

<?php
// 开发环境:显示所有错误
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

// 生产环境:不显示错误但记录到日志
ini_set('display_errors', '0');
ini_set('log_errors', '1');
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
?>
生产环境绝对不要 display_errors = On。详细的错误信息可能泄露代码结构、数据库凭据等敏感信息。将错误记录到日志文件,用户只看到友好的错误页面。

常用调试函数

函数用途
var_dump($var)输出变量的类型和值
print_r($var)以可读格式输出变量
debug_backtrace()获取调用栈信息
error_log($msg)将消息写入错误日志

一句话小结

try/catch 处理可预期的错误,用 throw 在业务层主动抛出异常,用 set_exception_handler 做全局兜底。生产环境关闭 display_errors,把错误记录到日志而非暴露给用户。下一篇讲 Session 与 Cookie

最后更新于