PHP异常捕获仅对Exception及其子类有效,无法捕获Warning、Notice或Fatal Error等Error体系错误;必须显式throw异常或由系统抛出如PDOException才能被catch;多个catch需按子类到父类顺序排列,PHP 8+支持多类型合并捕获;finally确保资源清理,空catch须至少记录日志。
PHP异常捕获不是“能抓就抓”,而是有明确边界和设计逻辑的。它只对 Exception 及其子类 有效,对 Warning、Notice、Fatal Error 等错误类型完全无感——这些属于 PHP 的 Error 类体系,与 Exception 平行,都实现 Throwable 接口,但语义和处理方式完全不同。
能被 try-catch 捕获的只有显式抛出的异常对象:
throw new Exception("...") 或自定义异常类实例PDOException(数据库操作失败)、InvalidArgumentException(参数非法)、PHP 7.3+ 的 JsonException(启用 JSON_THROW_ON_ERROR 时)以下情况 完全绕过 try-catch:
file_get_contents("missing.txt") → 触发 E_WARNING,不抛异常foo() → Fatal error: Uncaught Error,脚本立即终止Class not found)→ 全属 Fatal Error,catch 块根本不会执行多个 catch 必须按 子类在前、父类在后 排列,否则具体异常会被泛化 catch 提前吞掉:
立即学习“PHP免费学习笔记(深入)”;
catch (PDOException $e) → catch (RuntimeException $e) → catch (Exception $e)
Exception 放最前,后面所有子类 catch 都失效catch (PDOException | RuntimeException $e),适合共用处理逻辑的场景finally 块无论是否抛异常、是否被捕获,都会执行。这是释放资源不可替代的机制:
finally 中显式关闭或清理catch 处理——如果没异常,catch 不执行,资源就泄漏了finally 中的 return 会覆盖 try 或 catch 中的返回值,慎用写 catch (Exception $e) { } 等同于主动屏蔽问题:
error_log($e->getTraceAsString(), 3, '/var/log/php/app.log');
echo $e->getMessage() 或直接输出堆栈,防止敏感路径/配置泄露throw 代替 if),这会让逻辑难以追踪