catch(throwable $e)是唯一能捕获error的写法,因php 7+中error与exception同为throwable子类但互不继承;需用instanceof区分处理,error应中止逻辑并记录堆栈,exception可业务化响应。

catch(Throwable $e) 是唯一能捕获 Error 的写法
PHP 7+ 将 Error 和 Exception 统一为 Throwable 接口的实现类,但 catch(Exception $e) 完全捕获不到 Error(比如 ParseError、FatalError、TypeError)。只有显式写 catch(Throwable $e) 才能兜住所有崩溃性问题。
常见错误现象:
- 用
catch(Exception $e)包裹了json_decode($malformed, true),结果 JSON 格式严重错误时没被捕获,直接 500 - 调用不存在的方法(如
$obj->nonexistent())触发Error,但catch(Exception)无响应
注意:这不是语法错误,而是类型不匹配——Error 不继承 Exception,它俩是同级兄弟类。
区分业务异常和引擎错误,靠 instanceof + 类名判断
捕获到 Throwable 后,不能一概而论地记录日志或返回用户提示。你得立刻判断它到底是「可预期的业务失败」还是「不该发生的底层崩溃」。
实操建议:
- 用
$e instanceof Exception判断是否为业务/自定义异常(比如ValidationException、ApiConnectionException) - 用
$e instanceof Error判断是否为引擎级错误(如ParseError、TypeError、AssertionError) - 对
Error类型,应立即中止后续逻辑,记录完整堆栈,并返回通用错误页(绝不暴露敏感路径或变量名) - 对
Exception类型,可按需返回结构化错误码、重试提示或降级数据
示例片段:
try {
doRiskyThing();
} catch (Throwable $e) {
if ($e instanceof Error) {
error_log('FATAL ENGINE ERROR: ' . $e->getTraceAsString());
http_response_code(500);
echo 'Service unavailable';
exit;
}
// 此处 $e 必为 Exception 或其子类
logBusinessException($e);
renderUserFriendlyError($e->getMessage());
}
PDO::ERRMODE_EXCEPTION 是触发 Error 的关键开关
很多开发者以为 PDO 错误天然就是 Exception,其实不是。默认模式(PDO::ERRMODE_SILENT)下,出错只设错误码,不抛异常;PDO::ERRMODE_WARNING 发警告但不中断;只有 PDO::ERRMODE_EXCEPTION 才会真正抛出 PDOException(它是 Exception 子类)。
容易踩的坑:
- PHP 8.0+ 默认已启用
PDO::ERRMODE_EXCEPTION,但旧项目迁移后可能仍保留手动设置为SILENT,导致数据库错误静默失败 - 忘记在连接后立即设置:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION),结果query()出错时不进catch -
PDOException是Exception,不是Error,所以即使开了异常模式,它也不会被catch(Error $e)捕获
finally 中 return 会覆盖 try/catch 的返回值
这是极易被忽略的语义陷阱:只要 finally 块里有 return,无论 try 还是 catch 返回什么,最终函数返回的都是 finally 的值。
典型场景:
- 在
finally里做资源清理时顺手写了return true;,结果本该抛出的异常被吞掉,调用方收不到错误信号 - 事务处理中,
try提交成功返回['status' => 'ok'],catch返回['status' => 'error'],但finally里return ['cleanup' => 'done'],外部永远收不到状态
解决方法:不要在 finally 中写 return;如需返回值,应在 try 或 catch 显式赋值,finally 只负责清理。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











