ThinkPHP 6 的错误页面由 config/exception.php 中的 'render' 回调统一控制,需返回 Response 实例;404 需在 render 中显式判断 HttpException 并用 view()->fetch() 渲染,同时关闭 Web 服务器级 error_page 并清除运行时缓存。

ThinkPHP 6 的 app_exception 配置在哪改
错误页面不是靠模板文件路径硬编码决定的,而是由异常处理机制接管后统一响应。ThinkPHP 6 默认使用 think\exception\Handle 类,但自定义入口在配置里。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 修改
config/exception.php文件(若不存在可复制vendor/topthink/framework/src/think/exception/Handle.php对应逻辑参考) - 关键配置项是
'render'回调函数,它接收$e(异常对象),返回Response实例 - 不要动
app/exception/Handle.php里的report()方法——那是记录日志用的,不影响页面展示 - 如果用了多应用模式,注意配置是否落在对应应用目录下(如
app/demo/config/exception.php)
怎么让 404 错误走自定义模板而不是白屏
404 是 think\exception\HttpException,但它不经过全局 app_exception 配置,而由路由层提前拦截。直接 throw 新的 HttpException(404) 不会触发你写的 render 回调。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 在
config/exception.php的'render'函数中,显式判断instanceof HttpException并分发处理 - 模板路径别写死成
view/404.html,用view()->fetch('error/404')更稳妥,避免视图引擎未初始化报错 - 确保
config/app.php中'debug' => false,否则开发环境下无论如何都会显示调试页 - 注意:Nginx/Apache 若配置了
error_page 404,会直接截获 HTTP 状态码,绕过 PHP 层——先关掉服务器级 404 转发再调试
render 回调里怎么安全输出变量又不暴露敏感信息
直接 dump($e) 或 print_r($e->getTrace()) 在线上等于把数据库密码、路径全打出来。ThinkPHP 默认 debug 页面之所以安全,是因为它做了字段过滤和上下文脱敏。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 只取
$e->getMessage()和$e->getStatusCode()(如果有),其他一律不透出 - 用
Env::get('APP_DEBUG', false)判断当前环境,仅 debug 模式下才允许渲染 trace 信息 - 避免在模板里直接 echo
$e->getFile()—— 可能泄露绝对路径,改成basename($e->getFile()) - 如果用了自定义异常类(比如继承
HttpException),记得重写getStatusCode()和getHeaders(),否则状态码可能仍是 500
为什么改了配置还是跳转到默认错误页
最常见原因是缓存没清,或者异常发生在容器初始化之前(比如 config 文件语法错误、扩展未加载),此时框架根本没跑起来,自然不会执行你的 render。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 删掉
runtime/cache/和runtime/container/目录,再试 - 临时在
public/index.php最顶部加var_dump('boot');,确认请求是否进到了框架启动流程 - 检查
config/exception.php是否 return 了一个合法数组,漏掉return [];会导致配置解析失败 - 如果用了 Swoole 或 RoadRunner,注意长连接下配置可能被复用,需重启服务进程而非只是刷新浏览器
真正麻烦的从来不是怎么写 render 回调,而是异常发生时框架还没来得及加载你的配置——这时候连日志都记不了,只能靠服务器 error_log 或 strace 抓原始请求流。


















