try/catch仅捕获Exception或Throwable子类异常,不捕获E_NOTICE、E_WARNING等传统错误;需用set_error_handler转错误为异常或@抑制符配合返回值检查。
PHP 5.3+ 中 try/catch 能捕获哪些异常
try/catch 只捕获继承自 Exception 或 Throwable 的异常,**不捕获 E_NOTICE、E_WARNING 等传统错误**。这是最常被误解的一点:写个 try 包住 file_get_contents('missing.txt'),照样报 Warning: file_get_contents(...): failed to open stream...,根本进不了 catch。
实际可用的组合方式只有两种:
- 用
set_error_handler()把错误转成异常,再由try/catch统一处理(推荐) - 对特定函数搭配错误抑制符
@+ 手动检查返回值(简单场景可用,但会丢失错误上下文)
用 set_error_handler 实现错误转异常的兼容写法
PHP 7+ 支持把大多数错误(除 E_PARSE、E_COMPILE_ERROR 等编译期错误)转为 Error 实例,而 PHP 5.3–5.6 只能靠自定义 handler 抛出 Exception。下面这段代码在 PHP 5.3 至 8.3 均可运行:
function error_to_exception($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
return;
}
throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler('error_to_exception');
之后你就能这样写:
立即学习“PHP免费学习笔记(深入)”;
try {
$data = file_get_contents('/nonexistent');
} catch (ErrorException $e) {
echo "文件读取失败:", $e->getMessage();
}
- 注意必须在
set_error_handler()后再触发错误,否则无效 -
ErrorException是 PHP 内置类,兼容所有版本,比手写新异常类更稳妥 - 别忘了在 CLI 模式下,
error_reporting(E_ALL)可能默认关闭部分级别,建议显式开启
@ 错误抑制符的真实行为与风险
@ 不是“静默忽略”,而是临时将 error_reporting 设为 0,执行完立刻恢复。它**无法抑制 Parse Error、Fatal Error,也不能跨作用域生效**(比如函数内用了 @,但错误发生在被调用的另一个函数里,仍会报出)。
常见误用: