ThinkPHP6全局异常捕获与日志写入需正确配置ExceptionHandle类:启用自定义处理器、重写report()精准控制日志落盘、render()统一响应并脱敏敏感信息、关闭show_error_msg、开启realtime_write确保日志不丢失。

ThinkPHP6 的全局异常捕获和日志写入,核心在于正确配置 ExceptionHandle 类,并配合框架日志系统,确保所有未被捕获的业务与系统异常都能被记录、脱敏、统一响应。关键不是“能不能记”,而是“记什么、何时记、怎么不重复记”。
确认异常处理器已启用并接管 render 流程
TP6 默认使用 app/exception/Handler.php(继承 hinkexceptionHandle)。必须确保该类的 render() 方法被实际调用,而不是直接返回 parent::render() —— 否则会走默认 HTML 错误页逻辑,跳过你自定义的日志控制。
- 检查
config/app.php中是否已注册该处理器:'exception_handle' => '\app\exception\Handler' -
render()方法中不要无条件调用parent::render();应先做类型判断,再决定是否交由父类处理 - 若想让所有异常都走 JSON 响应(如 API 场景),就在
render()中统一返回$this->json(...)或自定义响应对象
在 report() 中精准控制日志写入行为
框架会在异常抛出后、进入 render() 前,自动调用 report() 方法。这里才是日志落盘的主入口,但默认会记录所有异常——包括你不想留痕的业务异常(如参数校验失败)。
- 重写
report()方法,用parent::report($exception)保留基础能力 - 通过
$this->ignoreReport数组排除无需日志的异常类,例如:ValidateException::class、HttpException::class(404/405 等) - 若自定义了
AppException等业务异常,务必将其加入$dontReport或在shouldReport()中返回false,避免干扰错误排查
生产环境必须关闭敏感信息输出
即使日志写入正常,线上仍可能因配置疏漏暴露 SQL、路径、堆栈等——这不是日志问题,而是响应内容没脱敏。
立即学习“PHP免费学习笔记(深入)”;
- 确认
config/app.php中'show_error_msg' => false已生效(TP6.1+ 支持) - 在
render()中对非调试环境手动裁剪:只保留$e->getMessage(),过滤$e->getFile()、$e->getLine()和完整 trace - 建议将业务错误码与提示映射为前端友好的字符串(如 “token 已过期” 而非 “TokenExpiredException”),避免直接透出异常类名
验证日志是否真实写入
ThinkPHP 日志默认在请求结束时批量写入,若中间用了 exit、die 或协程中断,会导致日志丢失。
- 日志通道配置中开启
'realtime_write' => true可强制即时落盘(适合调试) - 查看
runtime/log/下按日期生成的文件,确认有 ERROR 级别记录,且内容不含堆栈或路径 - 主动抛一个测试异常(如
throw new Exception('test log')),观察日志内容与接口响应是否符合预期



















