Yii2默认不解析application/json请求体,需在config/web.php的request组件中配置parsers=>['application/json'=>'yii\web\JsonParser'],否则post()和getBodyParam()均返回空;配置后JSON数据自动转为PHP数组,支持嵌套访问与Model::load()。

Yii 框架的 RESTful 接口默认收不到 application/json 的 POST 数据,不是前端没发对,也不是后端代码写错了——是 Yii2 的 request 组件根本没配 JSON 解析器,post() 和 getBodyParam() 都会返回空。
为什么 Yii::$app->request->post() 拿不到 JSON 数据
Yii2 默认只从 $_POST 读取数据,而 PHP 不会自动解析 application/json 请求体到 $_POST(Web 服务器不处理它)。所以即使前端用 fetch 或 axios 发了 {"name":"test"},post() 仍返回空数组。
-
getBodyParam('name')本质依赖getBodyParams(),而后者只在parsers配置命中时才调用yii\web\JsonParser - 没配
parsers时,getBodyParams()会 fallback 到mb_parse_str($rawBody),但 JSON 字符串无法被mb_parse_str正确解析成键值对 - 错误现象:打印
Yii::$app->request->post()是空数组,getRawBody()能拿到原始 JSON 字符串,但手动json_decode()又重复造轮子
必须在 config/web.php 里配置 parsers
这是唯一可靠、框架级生效的解法。不改配置,任何控制器里手动 json_decode(getRawBody()) 都只是补丁,且容易漏掉容错、类型转换、异常捕获。
- 在
components['request']下添加'parsers' => ['application/json' => 'yii\web\JsonParser'] - 如果前端可能带
charset(比如application/json; charset=UTF-8),注意 Yii2 不自动截取;前的内容——必须确保Content-Typeheader 精确匹配键名,或额外加一条'application/json; charset=UTF-8' => 'yii\web\JsonParser' - 别漏掉
cookieValidationKey,否则请求可能因 CSRF 校验失败直接 400 - 配置后,
post()、getBodyParam()、getBodyParams()全部可用,行为和表单提交一致
yii\web\JsonParser 解析后数据怎么用
配置生效后,JSON body 会被自动解析为 PHP 关联数组,存入 request 内部缓存,后续所有 post() 调用都走这个缓存,无需重复解析。
-
Yii::$app->request->post('name')→ 直接取字段值(等价于$data['name']) -
Yii::$app->request->post()→ 整个解析后的数组,可用于批量校验或传给 Model::load() - 嵌套结构(如
{"user":{"name":"a","age":25}})也能正常访问:post('user')['name'] - 注意:如果 JSON 语法错误(如多逗号、单引号),
JsonParser会抛BadRequestHttpException,状态码 400,不用自己 catch
别在控制器里手动 json_decode(getRawBody())
除非你明确需要绕过框架解析逻辑(比如要原样保存 raw JSON 字段),否则手动解析是反模式。
- 重复解析:
getRawBody()多次调用可能失败(php://input只能读一次) - 丢失一致性:
post()和手动解析结果不统一,Model::load()等方法无法直接使用 - 忽略边界:没处理
Content-Type不匹配、空 body、编码异常等情况,线上容易 500 - 兼容性风险:Yii3 已重构 request 解析机制,硬编码解析逻辑不利于升级
真正容易被忽略的是 Content-Type 的精确匹配规则——Yii2 的 parsers 键是严格字符串比对,不支持 MIME type 的 subtype wildcards 或参数剥离。发请求时 header 必须干净,或者配置项得写全。


















