yii\rest\ActiveController自定义动作如何更优读取JSON输入
Yii2 处理JSON请求参数的优化方案
你当前手动读取bodyParams的方式可以正常运行,还有两种更符合框架设计特性的实现方案,可按需选择:
方案1:实现JSON参数自动绑定到动作方法参数
Yii2默认的动作参数绑定只会从路由匹配参数、URL查询参数中取值,只要重写控制器的bindActionParams方法,把解析后的JSON请求体参数合并到参数源中,就能实现你想要的“直接将JSON输入读取为动作方法参数”的效果。
如果要让当前控制器下所有动作都支持这个特性,直接在控制器中添加如下方法:
public function bindActionParams($action, $params) { $request = Yii::$app->request; // 合并路由参数、GET查询参数、JSON/表单请求体参数 $mergedParams = array_merge( $request->getQueryParams(), $request->getBodyParams(), $params ); return parent::bindActionParams($action, $mergedParams); }
配置完成后,测试动作可以简化成如下写法,不需要手动逐行提取bodyParams:
public function actionTest($one = false, $two = false, $three = false) { return [ 'params' => [ 'one' => $one, 'two' => $two, 'three' => $three, ] ]; }
如果项目中多个控制器都需要这个能力,可以把这段bindActionParams逻辑写到公共的API基类控制器中,一次配置即可全局生效。
方案2:用表单模型统一接收、校验参数
如果接口参数较多、有明确校验规则(比如必填、类型限制、格式校验),更推荐用Yii自带的Model类来处理参数,符合框架最佳实践,后期维护成本更低。
- 先创建专门的参数接收模型:
<?php namespace common\models; use yii\base\Model; class TestForm extends Model { public $one; public $two; public $three; public function rules() { return [ [['one', 'two', 'three'], 'required'], [['one', 'two', 'three'], 'integer'], // 可按需添加其他校验规则,比如范围校验、格式校验等 ]; } }
- 在控制器动作中直接加载、校验参数:
public function actionTest() { $form = new TestForm(); $form->load(Yii::$app->request->getBodyParams(), ''); if (!$form->validate()) { return [ 'code' => 400, 'message' => '参数错误', 'errors' => $form->errors ]; } // 业务逻辑中直接通过 $form->one、$form->two、$form->three 取值即可 return [ 'params' => [ 'one' => $form->one, 'two' => $form->two, 'three' => $form->three, ] ]; }
注意事项
你当前在verbs()方法中给test动作配置的允许请求方法是GET,不符合HTTP规范:GET请求的语义是资源查询,不应该携带请求体,部分Web服务器、网络代理、HTTP客户端会主动丢弃GET请求的请求体内容,建议将该动作的允许方法改为POST,避免线上出现参数丢失的问题:
public function verbs() { $verbs = parent::verbs(); $verbs['test'] = ['POST']; return $verbs; }
内容的提问来源于stack exchange,提问作者trejder
相关产品推荐
相关产品推荐

