如何在Yii2 RESTful服务中验证来自GET请求的params

时间:2016-04-15 10:34:00

标签: json rest validation get yii2

我有一个language参数需要发送到我的文档端点。所以我必须验证用户是否已在他的GET请求中发送了此参数。

在我的模型中制定规则没有做任何事情:

public function rules()
{
    return [
        [['language'], 'required'],
    ];
}

因此我尝试了这个:

1)我创建了ParamsValidator类:

<?php
namespace app\modules\v1\components;

use yii\web\UnprocessableEntityHttpException;
use yii\base\Component;
use Yii;

/**
 * Class that is responsible for validating input params.
 */
class ParamsValidator extends Component
{
    public function validate($params)
    {
        if (!isset($params['language'])) {
            throw new UnprocessableEntityHttpException("Language parameter is required");
        }
    }
}

我在我的控制器validate()方法中调用其init()方法:

public function init()
{
    $this->_params = Yii::$app->request->queryParams;

    $validator = new ParamsValidator();
    $validator->validate($this->_params);
}

这种工作。代码有效,但我回复得很难回复。而不是很好的JSON响应,我从这样开始得到一堆html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Unprocessable entity (#422)</title>
        <style>
        body {
            font: normal 9pt "Verdana";
            color: #000;
            background: #fff;
        }

而不是这个html,我想要一些不错的JSON响应:

{
    "name": "Forbidden",
    "message": "You are not authorized to do this.",
    "code": 0,
    "status": 403,
    "type": "yii\\web\\ForbiddenHttpException"
}

您看到的这个好的JSON错误是由:

$behaviors['authenticator'] = [
    'class' => HttpBasicAuth::className(),
    'auth' => [$this, 'authenticate']
];

但显然我的Validator没有这样做。

问题:

1)如何验证通过GET请求来的params?
2)如果我的方法是正确的,如何获得这个漂亮的JSON错误响应?

1 个答案:

答案 0 :(得分:1)

一个简单的选择是通过添加内部控制器来覆盖ActiveController::checkAccess方法:

public function checkAccess($action, $model = null, $params = [])
{
    if ($action === 'index' or $action === 'view') 
    {
        $params = Yii::$app->request->queryParams;
        if (!isset($params['language'])) {
             throw new \yii\web\ForbiddenHttpException('You are not authorized to do this.');
        }

    }
}

如果您需要在模型级别执行此操作,则需要使用addError()方法而不是直接抛出错误。您的模型实例将在调用其validate方法时保留它。然后在你的动作中你可以简单地返回它。它将被序列化,错误将以正确的格式输出。有很多方法可以实现这一目标。一个简单的例子可能是使用load方法在验证之前将查询和正文参数传递给模型(可能需要方案):

$queryParams = Yii::$app->request->queryParams;
$bodyParams  = Yii::$app->request->bodyParams;

$params = array_merge($queryParams,$bodyParams );

$model = new $modelClass;
$model->load($params , '');

if ($model->validate() === false) return $model;
else {
   // do whatever you need
}