ThinkPHP 8.0 默认不自动解析 application/json 请求体,需手动读取 $request->getContent() 并 json_decode;推荐使用 $request->param()(需 Content-Type 正确且 body 未被提前消费)或统一中间件预解析并 merge 到参数池。

ThinkPHP 8.0 默认不自动解析 Content-Type: application/json 的请求体,前端用 fetch 或 axios.post(url, {data}) 发送 JSON 数据时,$request->post() 和 input('post.xxx') 都会返回空——因为 PHP 的 $_POST 数组只填充 application/x-www-form-urlencoded 和 multipart/form-data 类型的请求,JSON 是原始 body,必须手动读取并解码。
直接读取并解码原始请求体
在控制器方法中使用:
-
$raw = $request->getContent();获取原始 JSON 字符串 -
$data = json_decode($raw, true);转为关联数组(注意加true参数) - 若解析失败,检查
$raw是否为空或非法 JSON(如单引号、尾逗号、BOM 头)
用 $request->param() 的兼容写法(推荐)
$request->param() 在 TP8.0 中已支持自动识别 JSON body,但需满足两个前提:
PHP 8.5.12 RC 1 候选版修复 BZ2、DOM、PDO、Opcache/JIT 和扩展内存安全问题,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 请求头
Content-Type必须是application/json - 框架未被中间件提前消费 body(例如日志中间件调了
getContent()一次后,再次调用会返回空) - 可安全使用:
$id = $request->param('id', null, 'intval');,它会从 JSON body、GET、POST 等多源自动提取并类型转换
统一中间件预解析(适合全站 API)
若项目大量接口接收 JSON,可在中间件中一次性解析并挂载到 Request 对象:
立即学习“PHP免费学习笔记(深入)”;
- 新建中间件
app/middleware/ParseJsonBody.php - 在
handle()中判断:if ($request->header('content-type') === 'application/json' && !$request->isGet()) - 执行
$data = json_decode($request->getContent(), true) ?: []; - 用
$request->merge($data)将其合并进参数池,后续$request->param()就能直接取值 - 注意:不要覆盖已有同名 GET/POST 参数,避免逻辑错乱
验证与调试要点
常见问题不是代码写错,而是环境或格式干扰:
- 前端发的是
{name:'张三'}(单引号)→ PHPjson_decode失败 → 改为双引号 - 响应前有
echo、var_dump或 BOM 输出 → 破坏 JSON 结构 → 检查文件编码(UTF-8 无 BOM) - 调试模式开启(
app_debug = true)→ 异常堆栈混在 JSON 前 → 返回变成非法 JSON → 关闭调试或用中间件拦截异常流 - 跨域请求带 cookie 或自定义 header → 浏览器先发 OPTIONS → 若路由没配,预检失败 → 后续 JSON 请求被静默拦截


















