try-catch仅捕获throwable对象(exception及php 7.1+的error类),不捕获e_notice、e_warning等传统错误;需用set_error_handler转为errorexception才能捕获,且无法处理e_error、e_parse等致命错误。

PHP 的 try-catch 本来就不抓所有错误
它只捕获 Exception 和实现了 Throwable 的对象(PHP 7.1+ 的 Error 类),而像 E_NOTICE、E_WARNING 这类传统错误,根本不是异常对象,只是 PHP 引擎发出来的“信号”,默认不会进 catch 块。
常见表现:
- 访问未定义变量(
$undefined_var)触发E_NOTICE,try-catch(Exception)完全静默 -
include 'missing.php'报Warning: include(): Failed opening...,同样不被捕获 - 语法错误(如
parse error)在脚本加载阶段就中止,try根本没机会执行
catch(Throwable $t) 是 PHP 7.1+ 的最低安全线
如果你只写 catch(Exception $e),那 TypeError、ParseError(部分)、ArgumentCountError 等 Error 子类全被漏掉——它们不是 Exception 的子类,但都实现了 Throwable。
正确写法是:
try {
// 可能出错的代码
$result = json_decode($badJson, true, 512, JSON_THROW_ON_ERROR);
} catch (Throwable $t) {
error_log('Caught: ' . $t::class . ' - ' . $t->getMessage());
// 统一兜底处理
}
注意:JSON_THROW_ON_ERROR 是个关键开关,不加它,json_decode 即使失败也只返回 null,不会抛出任何东西。
想让 E_WARNING/E_NOTICE 进 catch?得手动转成异常
PHP 不自动把传统错误变成异常,必须靠 set_error_handler() 中转。但要注意:它不能捕获 E_ERROR、E_PARSE 等致命错误,只对可恢复错误有效。
典型做法:
- 在入口文件(如
index.php)开头注册处理器 - 把
E_WARNING、E_NOTICE等转为new ErrorException() - 确保该异常类也实现
Throwable(PHP 5.5+ 默认满足)
示例:
set_error_handler(function ($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
return;
}
throw new ErrorException($message, 0, $severity, $file, $line);
});
<p>try {
echo $undefined_var; // 现在会抛出 ErrorException,被 catch(Throwable) 捕获
} catch (Throwable $t) {
echo 'Handled: ' . $t->getMessage();
}</p>
最容易被忽略的三个点
第一,trigger_error() 发出的错误默认不进 catch,除非你用上面的 set_error_handler 转换;
第二,set_exception_handler() 是全局兜底,和 try-catch 是两套机制,别混用还指望它补漏;
第三,某些扩展(如 cURL、PDO)的底层错误行为不一致——比如 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION 必须显式开启,否则数据库错误只返回 false,不抛异常。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











