ThinkPHP全局异常处理本质是注册+拦截+分流,需继承think\exception\Handle并重写render方法,按异常类型分流响应,配置exception_handle路径,建议分层设计业务异常并记录日志。

ThinkPHP 的全局异常处理类本质是接管框架默认的错误捕获流程,把各类运行时异常、PHP 错误、脚本终止等统一导向你定义的响应逻辑。核心不在“写一个类”,而在于“注册 + 拦截 + 分流”三个动作是否到位。
必须重写的 render 方法
自定义异常处理类需继承 think\exception\Handle,且必须重写 render() 方法。这个方法是所有未被捕获异常最终抵达的出口。它接收两个参数:$request(当前请求对象)和 $e(抛出的异常实例)。你的逻辑就在这里展开:
- 判断异常类型:用 instanceof 区分业务异常(如
BusinessException)、HTTP 异常(如HttpException)、系统级异常(Exception或Error) - 开发模式下可直接调用 parent::render($request, $e) 复用 TP 默认调试页
- 生产环境应屏蔽堆栈细节,返回结构化 JSON 或跳转至错误页面
- 注意 HTTP 状态码要与语义匹配:404 对资源不存在,400 对参数错误,500 对服务端故障
配置入口不能遗漏
仅写好类还不够,必须让框架知道“该用谁”。配置位置取决于版本:
-
TP5/TP5.1:修改
config.php中的'exception_handle' => '\app\common\exception\Http' -
TP6:在
app/provider.php容器定义中注册:'think\exception\Handle' => \app\common\exception\Http::class - 务必确认类路径拼写正确,命名空间与文件物理路径严格一致
- 若使用多应用模式(如 admin、api),需在对应应用目录下单独配置
业务异常建议分层设计
不推荐所有异常都 throw new Exception()。更合理的是建立轻量级业务异常体系:
立即学习“PHP免费学习笔记(深入)”;
- 定义基类
BaseException extends \Exception,含$code(HTTP 状态码)、$errorCode(业务码)、$msg(提示文案)属性 - 按场景派生子类:如
ValidateException(422)、ResourceNotFoundException(404)、AuthException(401) - 在 render 中统一识别这些子类,提取属性生成标准响应,避免 if-else 堆砌
别忘了错误日志和监控
异常处理不只是给用户看提示,更是排查问题的关键环节:
- 在 render 方法中调用
Log::error()记录异常详情(文件、行号、trace、请求参数) - 对非调试环境的 500 类错误,可额外触发告警(如发送钉钉/邮件、调用机器人接口)
- 确保
runtime/log/目录可写,否则日志会静默丢失 - 避免在 render 中再抛出新异常,否则可能造成无限递归或空白响应



















