Yii::$app->request->post()对JSON请求返回null,因PHP仅自动解析application/x-www-form-urlencoded和multipart/form-data;需配置'parsers'=>['application/json'=>'yii\web\JsonParser']或用getRawBody()手动解析。

直接用 Yii::$app->request->getRawBody() 就能拿到原始请求体,但多数时候你真正需要的是解析后的参数——这取决于前端发的是什么格式、后端有没有配对的解析器。
为什么 $request->post() 返回 null,但 getRawBody() 能拿到数据
这是最常见的现象,尤其在调用 iOS/Android 原生客户端或 fetch API 时。根本原因是:$_POST 只被 PHP 自动填充当 Content-Type 是 application/x-www-form-urlencoded 或 multipart/form-data;而 JSON 请求(Content-Type: application/json)不会触发该机制。
- 前端发的是
{"name":"test","id":123},Content-Type: application/json→$_POST为空 →$request->post()返回空数组 -
getRawBody()绕过 PHP 解析,直接读取php://input流 → 拿到原始字符串 - 但注意:
php://input只能读一次;多次调用getRawBody()会返回空字符串(除非已缓存)
怎样让 $request->post() 正常工作(推荐做法)
不用手动 json_decode(file_get_contents('php://input')),而是配置 Yii 的解析器,让框架自动处理。
- 在
config/web.php的components['request']中添加:
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
Content-Type: application/json(大小写不敏感,但不能带多余空格或参数如 charset=utf-8)$request->post('name')、$request->getBodyParams() 都能直接取到解析后的数组'*' 对应默认解析器,但优先匹配具体类型
getRawBody() 的坑与边界条件
它看似简单,实际容易踩几个隐性雷:
- PHP 的
enable_post_data_reading配置为Off时,php://input不可用(极少见,但容器环境可能被改) - 请求体超大(比如上传 base64 图片)且未设置
post_max_size/memory_limit,getRawBody()会返回 false 或截断 - 某些 Nginx 配置(如
client_max_body_size)会直接拦截大请求,根本到不了 PHP 层 - GET 请求调用
getRawBody()总是返回空字符串(因为没 body),别误以为出错 - 如果你在中间件或行为里提前读过
php://input(比如做签名验证),后续getRawBody()就拿不到东西了
调试时怎么快速确认问题在哪
别猜,直接看三样东西:
- 打印
Yii::$app->request->getContentType()—— 看是不是你预期的类型 - 打印
Yii::$app->request->getRawBody()—— 确认原始数据是否到达 - 打印
Yii::$app->request->getBodyParams()—— 看解析是否成功,空数组 ≠ 出错,可能是解析器没命中
最常被忽略的一点:解析器只在 getBodyParams() 第一次调用时触发,如果之前手动调过 getRawBody() 又没传给解析器,框架不会重试解析——它认为你已经接管了原始数据。


















