php try-catch 默认捕获不到 fatal error,因后者不属于 exception;php 7+ 需 catch (throwable $e) 才能捕获 error;应避免静默吞异常、滥用 return false、深层嵌套及生产环境暴露堆栈。

PHP try-catch 捕获不到 Fatal Error?
因为 try-catch 只捕获 Exception 及其子类,不捕获 Fatal Error(如 Call to undefined function、Class not found)。PHP 7+ 虽将部分错误转为 Error 类(继承自 Throwable),但默认仍不会被普通 catch (Exception $e) 捕获。
- 必须写成
catch (Throwable $e)或分别捕获Exception和Error - 常见漏写场景:框架里只 catch Exception,结果 500 错误没日志、监控收不到
-
set_error_handler()无法捕获 Fatal Error,只能用register_shutdown_function()+error_get_last()补救
什么时候该 throw 新异常,而不是直接 return false?
当调用方需要区分“业务失败”和“系统异常”,且希望统一处理(比如记录上下文、触发告警、回滚事务)时,必须抛异常。return false 只适合简单函数内部短路,比如 file_exists() 这类纯判断。
- 数据库操作失败、远程 API 超时、配置缺失——这些都该
throw new RuntimeException(...) - 避免在 catch 里静默吞掉异常,又不 re-throw,导致上游逻辑继续执行出错
- 自定义异常类建议继承
RuntimeException(非检查型)或LogicException,别直接 new Exception
try-catch 嵌套太深,怎么拆?
嵌套 try-catch 容易掩盖真实错误位置,也难维护。核心原则:每个 try 块只负责一个明确的、可能失败的外部交互点。
- 把文件读取、JSON 解析、DB 查询拆成独立方法,各自 try-catch,再由上层聚合处理
- 避免在循环里反复 try-catch,比如批量发短信,应捕获单次失败,记录错误 ID,而非让整个 foreach 中断
- 注意
finally不是万能清理口:如果 try 里已 die() 或 exit(),finally 不会执行;资源释放优先用unset()或对象析构(__destruct)
生产环境要不要关闭异常堆栈?
要关。直接输出 $e->getTraceAsString() 到前端,等于把路径、变量名、数据库配置片段全暴露出去。
- 开发环境开启
display_errors = On,生产环境设为Off,日志走error_log()或 monolog - 用户看到的提示必须脱敏:
throw new HttpException(500, '服务暂时不可用'),不是 'SQLSTATE[HY000]: General error: 1364 Field x doesn’t have a default value' - 敏感字段(如密码、token)进日志前必须过滤,哪怕在异常 message 里出现过一次也不行
InvalidArgumentException 报数据库连接失败,或者 log 时只记了 $e->getMessage() 却没带上请求 ID 和输入参数。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











