thinkphp控制器接收json请求时param()和post()无法获取数据,因二者仅处理表单编码且php不解析application/json;必须用input('')读取原始body并json_decode()解析,同时校验content-type、避免重复读取。

ThinkPHP控制器接收JSON请求,不能用 param() 或 post(),必须走 input('') 或 rawInput() 读原始 body 再手动 json_decode()。否则数据永远为空。
为什么 param() 和 post() 拿不到 JSON 数据
因为 param() 合并 GET/POST/路由变量,但只处理表单编码(application/x-www-form-urlencoded 或 multipart/form-data);post() 依赖 PHP 自动填充 $_POST,而原生 PHP 根本不解析 application/json 请求体。JSON 数据压根没进 $_POST,自然取不到。
-
param('user.name')在 JSON 请求下返回null或空字符串 -
post('id')总是空数组,哪怕 Postman 明明发了{"id":123} - 框架不会自动拦截、解析、填充——你得自己读流
正确接收方式:用 input('') + json_decode()
input('') 是 ThinkPHP 提供的原始 body 读取入口,等价于 file_get_contents('php://input'),且只读一次。配合 json_decode() 才算完整链路。
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 写法:
$json = input(''); $data = json_decode($json, true); - 必须加第二个参数
true,否则返回对象,用isset($data['key'])会报错 - 务必检查解析结果:
if (json_last_error() !== JSON_ERROR_NONE) { /* 返回400 */ } - 不要在同一个请求里多次调用
input(''),第二次开始返回空字符串
Content-Type 校验不能省
前端可能误发 text/plain 或漏设 header,后端若不校验,就会把非 JSON 当 JSON 解析,导致静默失败或报错。
- 校验写法:
$contentType = $_SERVER['CONTENT_TYPE'] ?? ''; if (strpos($contentType, 'application/json') !== 0) { throw new HttpException(415); } - Nginx 环境下注意配置
fastcgi_pass_request_headers on;,否则$_SERVER['CONTENT_TYPE']可能为空 - 别信前端 header,服务端必须主动判断——这是最常被跳过的安全环节
rawInput() 和 input('') 有什么区别
两者都读原始 body,但 rawInput() 是 ThinkPHP 6.1+ 新增方法,语义更明确;input('') 兼容性更好(TP5.1+ 都支持),行为一致。
- 推荐优先用
input(''),避免版本兼容问题 -
rawInput()不做任何截断或编码转换,和file_get_contents('php://input')几乎等价 - 都不支持与
multipart/form-data共存——上传文件时发 JSON 会丢数据
真正容易出问题的不是语法,而是忘了校验 Content-Type、重复读取 php://input、或把 json_decode() 的错误当业务逻辑处理。这些点一漏,调试时就只能靠猜。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










