直接return json($data)即可,但需确保请求被识别为API(如Accept头为application/json)、禁用ViewInit中间件、无前置输出、文件为UTF-8无BOM编码,且异常处理器中对JSON请求单独返回json()响应。

直接 return json($data) 就行,但框架默认行为容易让它“悄悄走错路”,返回 HTML 页面而不是 JSON。核心问题不是代码写错,而是请求识别、中间件拦截和输出环境没对齐。
检查请求是否被正确识别为 API
TP6 默认根据 Accept 头、X-Requested-With 或路由前缀决定响应格式。如果前端没带 Accept: application/json,或用了 fetch(不自动带 X-Requested-With),框架就可能 fallback 到 HTML 渲染。
- 在控制器里加一行调试:dump($request->expectsJson(), $request->isAjax(), $request->path()); 看哪一项为 true
- 强制走 JSON 路径:在路由定义时加 ->middleware('throttle:api') 或统一用 api/ 前缀,再配合 $request->routeIs('api.*') 判断
- Postman 测试时,手动设置 Header:Accept: application/json,不要只靠 Content-Type
关掉模板中间件干扰
ViewInit 中间件会把任何返回值当模板变量处理,哪怕你写了 return json(),它也可能把你塞进 HTML 模板里输出。
- 在路由分组中显式禁用:->withoutMiddleware(\think\middleware\ViewInit::class)
- 全局关闭(不推荐):注释 config/middleware.php 中的 ViewInit 行
- 确认没有在控制器方法末尾漏掉 return —— 只调用 json() 不 return,等于没写
异常响应也要走 JSON 流程
500 错误页是 HTML?说明异常处理器 render() 没接管 JSON 请求。默认情况下,TP6 对 AJAX/JSON 请求有内置处理逻辑,会绕过你的自定义 Handler。
立即学习“前端免费学习笔记(深入)”;
- 在 app/exception/Handler.php 的 render() 开头加判断:if ($request->expectsJson() || $request->header('X-Requested-With') === 'XMLHttpRequest') { return json(['code' => 500, 'msg' => $e->getMessage()], 500); }
- 别用 return view(...),必须包装成 Response:return response()->view('error', $data, 500);
- 确保 APP_DEBUG 关闭时,错误也不吐 HTML 堆栈 —— 生产环境应始终返回结构化 JSON 错误
验证文件编码与前置输出
一个隐藏空格、BOM 头或 warning 就会让 JSON 变成非法格式,浏览器看到的是 HTML 解析失败页或下载弹窗。
- 所有 PHP 文件(尤其 config/、route/、中间件、控制器)保存为 UTF-8 无 BOM 格式
- 删掉文件开头的空行、空格,禁止在 json() 前使用 echo/var_dump/print_r
- 开启 error_reporting(E_ALL),把 Notice/Waring 显出来 —— 访问未定义数组键这类警告会直接污染输出流
- 用 curl 测试原始响应:curl -I http://your.dev/api/test 看 Content-Type 是否为 application/json



















