TP6 API调试需同时满足APP_DEBUG=true、show_error_msg=true,并重写exception.php的render()方法强制JSON错误响应,否则因Accept头不匹配仍返回空白或HTML页。

TP6 的 API 调试不能只靠 APP_DEBUG = true,否则错误页面仍走 HTML 模板、JSON 接口返回空响应或 500,根本看不到真实报错堆栈。
为什么开启 APP_DEBUG 后 API 还是不显示错误详情
因为 TP6 默认异常处理器(ExceptionHandle)在 APP_DEBUG = false 时强制返回 HTML 错误页;即使开了调试,若请求头不是 Accept: text/html(比如 Postman 或前端 fetch 默认发 application/json),它仍可能 fallback 到空白 JSON 响应或 500。
- 检查
app/exception.php是否被修改过——官方默认实现会根据请求类型自动切换响应格式,但一旦自定义了该文件且没处理json场景,就失效 -
config/app.php中的show_error_msg必须设为true,否则即使调试开启,也会屏蔽错误信息 - 确保没全局启用
think\middleware\AllowCrossDomain类中间件却未正确设置Access-Control-Allow-Origin,某些 CORS 预检失败会导致浏览器静默吞掉错误响应
如何让 API 请求直接返回带堆栈的 JSON 错误
最稳的方式是重写 render() 方法,强制所有 API 请求(无论 Accept 头如何)都输出结构化 JSON 错误。
- 打开
app/exception.php,确认继承自\think\exception\Handle - 在
render()方法中加判断:if ($request->isAjax() || $request->header('accept') === 'application/json') - 内部用
json(['error' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()], 500)返回 - 别忘了在顶部
use think\Response;,否则json()函数不可用
.env 和 config/app.php 的关键配置项必须同步
两个地方的开关不一致会导致行为矛盾:比如 .env 写了 APP_DEBUG = true,但 config/app.php 里 'app_debug' => false,最终以配置文件为准。
立即学习“PHP免费学习笔记(深入)”;
-
.env文件必须放在项目根目录,且文件名就是.env(不能是.env.local或其他) - 生效的最小必要组合:
APP_DEBUG = true+SHOW_ERROR_MSG = true(后者控制是否向客户端暴露错误细节) -
config/app.php中的app_debug和show_error_msg值会被.env覆盖,但仅当.env存在且可读——上线环境删掉.env就自动关闭调试,无需改代码
调试时 curl / Postman 请求必须带正确 header
TP6 的异常响应格式判断依赖请求头,不显式声明,它就按「普通网页请求」处理。
- 测试时务必加上:
-H "Accept: application/json"(curl)或在 Postman 的 Headers 里手动加Accept: application/json - 如果用
php think run启动本地服务,注意它默认不支持 HTTP/2,某些 header(如大 trace)可能被截断,换php -S或 nginx 更可靠 - 避免在中间件里提前调用
$response->send(),否则异常 render 会被跳过,只看到空白响应
真正难的不是开开关,而是让「错误发生时,第一眼就看到文件名、行号、变量值」——这要求 exception.php 的 render() 精准识别 API 上下文,而不是依赖框架默认的「看 Accept 头猜意图」逻辑。很多团队卡在这一步,反复刷新页面却只看到 500,其实只是 header 没对上。



















