PHP异常处理中try-catch仅捕获可预期的运行时异常,无法捕获Fatal Error、E_NOTICE或E_WARNING;PHP 7+必须用catch(Throwable $e)覆盖Exception和Error,避免漏捕;需配合set_error_handler转换非致命错误,register_shutdown_function兜底致命错误,并在finally中专注资源清理。

PHP异常处理中,try-catch不是万能兜底开关,而是针对**可预期、可恢复的运行时异常分支**设计的结构化机制。规范使用的关键,在于明确它能捕什么、该捕什么、怎么捕才不掩盖问题。
只捕Throwable,别再只写Exception
PHP 7+ 中,致命错误(如 TypeError、ParseError、调用不存在的方法)属于 Error 类及其子类,它们继承自 Throwable,但**不继承 Exception**。仅写 catch(Exception $e) 会漏掉绝大多数崩溃性错误。
- 必须统一用
catch(Throwable $e)才能覆盖Exception和Error - PHP 5.x 不支持
Throwable,只能捕Exception,且无法捕获 Fatal Error - 若需区分类型,应按“具体→通用”顺序多级捕获:先
catch(TypeError $e),再catch(Exception $e),最后可选catch(Throwable $e)
不捕E_NOTICE、E_WARNING这类传统错误
try-catch 对 E_NOTICE(如访问未定义变量)、E_WARNING(如包含不存在文件)完全无效——它们是 PHP 错误(error),不是异常(exception)。这类问题靠 error_reporting() 和 set_error_handler() 管理。
-
echo $undefined_var;触发的是 Notice,不会进入任何catch块 -
file_get_contents('missing.txt')默认返回false,不抛异常;要让它抛异常,得手动封装:if ($content === false) throw new RuntimeException('读取失败'); - 混淆错误与异常,容易导致“以为捕住了,其实静默失败”
catch里别吞异常,更别裸throw
捕获后不做处理或简单 throw $e,等于白写 try-catch;而直接 throw new Exception(...) 又会丢失原始堆栈和上下文。
立即学习“PHP免费学习笔记(深入)”;
- 记录日志必须包含
$e->getMessage()、$e->getTraceAsString()(生产环境需脱敏) - 如需重新抛出,用异常链:
throw new AppException('业务操作失败', 0, $e); - 避免在
catch中执行可能再次抛异常的操作(如又连一次数据库),否则会覆盖原始错误
finally不是可有可无,而是资源清理刚需
finally 块无论是否发生异常都会执行,是释放资源(如关闭文件句柄、断开数据库连接、释放锁)的可靠位置。
- 即使
try或catch中有return,finally仍会先执行 - 注意:
finally中若有return,会覆盖前面所有return的值 - 不要在
finally里做业务逻辑判断或抛新异常,专注清理



















