tp6的json()方法失效根本原因是框架响应类型推导逻辑绕过:若请求未带accept: application/json或config/app.php中default_return_type设为html,即使return json($data)也会退化为html包裹json;同时$request->input()不解析application/json请求体,须改用$request->json()。

TP6 的 json() 方法没生效,Content-Type 还是 text/html
根本原因不是你漏写了 header,而是 json() 被框架的响应类型推导逻辑绕过了。TP6 默认会根据请求头的 Accept 或配置项 default_return_type 决定返回格式——哪怕你写了 return json($data),如果请求没带 Accept: application/json,或者 config/app.php 里 'default_return_type' => 'html',它就会退化成 HTML 包裹的 JSON 字符串。
实操建议:
- 强制显式调用:
return json($data, 200)->header('Content-Type', 'application/json'); - 检查配置文件:
config/app.php中确认'default_return_type' => 'json' - Postman/curl 测试时必须带上:
-H "Accept: application/json"(不能只靠Content-Type: application/json) - 避免混用:控制器里别同时出现
echo、var_dump()或未捕获的 Notice,任何前置输出都会让json()失效并返回空或损坏 JSON
前端发了 application/json,但 $request->input() 拿不到数据
这不是 Content-Type 设置问题,而是 TP6 默认根本不解析 application/json 请求体。$request->input() 只处理 application/x-www-form-urlencoded 和 multipart/form-data,对 JSON 字段完全无视——所以 {"name":"张三"} 发过去,$request->input('name') 一定为 null。
正确做法是改用 $request->json():
-
$request->json('name')直接取顶层字段 -
$request->json('user.name')支持点号语法取嵌套字段 - 确保前端
Content-Type是严格application/json,不要写成application/json; charset=utf-8(TP6.0.x 部分版本会因此跳过解析) - 调试时加一句:
dump($request->isJson());确认框架是否识别为 JSON 请求
手动 echo json_encode() 后 Content-Type 仍是 text/html
这是最典型的“绕过框架响应层”错误。PHP 默认输出类型就是 text/html,echo json_encode($data) 只是往响应体里塞字符串,不自动设头。浏览器按 HTML 解析,自然报 Unexpected token {。
必须补 header,且顺序不能错:
- header 必须在任何输出之前调用:
header('Content-Type: application/json; charset=utf-8'); - 中文乱码?TP6.0 不支持全局
JSON_UNESCAPED_UNICODE配置,得手动加:echo json_encode($data, JSON_UNESCAPED_UNICODE); - 绝对避免:
json(json_encode($data))—— 双重编码会导致字符串变成"{"name":"\u5f20\u4e09"}" - 更稳妥的做法是回归框架:
return response($data)->contentType('application/json');
CORS 场景下 Content-Type 正确但前端 still fails
跨域时 Content-Type 和 CORS 头是两件事,缺一不可。即使你设了 application/json,如果没配全预检响应头,浏览器会在 OPTIONS 阶段就拦截,根本不会发 POST。
关键点:
- OPTIONS 请求必须被正确响应,不能 404 或 405;TP6 默认中间件不处理 OPTIONS,需手动加路由或中间件拦截
-
Access-Control-Allow-Headers必须显式包含Content-Type:header('Access-Control-Allow-Headers: Content-Type, Authorization'); -
Access-Control-Allow-Methods必须含OPTIONS:header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); - 若前端带
credentials: 'include',Access-Control-Allow-Origin不能为*,且要加Access-Control-Allow-Credentials: true
最容易被忽略的是:预检请求和实际请求是两个独立 HTTP 事务,CORS 头必须在两个响应中都存在,不能只在控制器里写一次。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











