错误与异常处理
这篇讲 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。
最后更新于