yii2 在控制器中驗證請求參數

寫api接口時通常會在控制器中簡單驗證參數的正確性。php

使用yii只帶驗證器(由於比較熟悉)實現有兩種方式(效果都不佳)。web

  1. 針對每一個請求單獨寫個 Model, 定義驗證規則並進行驗證。 缺點:寫好多參數驗證的 Model 類。
  2. 使用 獨立驗證器 中提到的 $validator->validateValue() 方法直接驗證變量值。缺點:寫實例化不少驗證器對象。

有麼有「一勞永逸」的作法,像在 Model 中經過 rules 方法定義驗證規則並實現快速驗證的呢?有!api

使用方法(實現效果)

namespace frontend\controllers\api;

use yii\web\Controller;
use common\services\app\ParamsValidateService;

class ArticleController extends Controller
{
    // 文章列表
    public function actionList()
    {
        $PVS = new ParamsValidateService();
        
        $valid = $PVS->validate(\Yii::$app->request->get(), [
            ['category_id', 'required'],
            ['category_id', 'integer'],
            ['keyword', 'string'],
        ]);
        
        if (!$valid) {
            $this->apiError(1001, $PVS->getErrorSummary(true));
        }
        
        //...
    }
    
    // 新增文章
    public function actionPost()
    {
        $PVS = new ParamsValidateService();
        
        $valid = $PVS->validate(\Yii::$app->request->get(), [
            [['category_id', 'title', 'content'], 'required'],
            ['category_id', 'integer'],
            [['title'], 'string', 'max' => 64],
            [['content'], 'string'],
        ]);
        
        if (!$valid) {
            $this->apiError(1001, $PVS->getErrorSummary(true));
        }
        
        //...
    }
    
    // 文章刪除
    public function actionDelete()
    {
        $PVS = new ParamsValidateService();
        
        $valid = $PVS->validate(\Yii::$app->request->get(), [
            ['article_id', 'required'],
            ['article_id', 'integer'],
        ]);
        
        if (!$valid) {
            $this->apiError(1001, $PVS->getErrorSummary(true));
        }
        
        //...
    }
}

實現方法

定義參數驗證模型

定義參數驗證模型 ParamsValidateModel,繼承 yii\db\ActiveRecord,重寫 attributes() 方法,主要功能:app

  • 驗證規則可從對象外部進行設置。
  • 從驗證規則中獲取可賦值的屬性。
<?php
namespace common\models\app;

use yii\db\ActiveRecord;

class ParamsValidateModel extends ActiveRecord
{
    /**
     * @var array 驗證規則
     */
    private $_rules = [];

    private $_attributes = [];

    // 設置驗證規則
    public function setRules($rules)
    {
        $this->_rules = $rules;

        foreach ($rules as $item) {
            $this->_attributes = array_unique(array_merge($this->_attributes, (array)$item[0]));
        }
    }

    // 重寫獲取驗證規則
    public function rules()
    {
        return $this->_rules;
    }

    // 設置可用屬性列表
    public function attributes()
    {
        return $this->_attributes;
    }
}

定義參數驗證服務類

定義參數驗證服務類,主要功能有:frontend

  • 設置參數列表和參數規則列表。
  • 使用 參數驗證模型 進行驗證和存儲驗證錯誤消息。
  • 使用魔術方法獲取 參數驗證模型 中的驗證錯誤消息。
<?php
namespace common\services\app;

use common\models\app\ParamsValidateModel;
use yii\base\Component;

/**
 * Class ParamsValidateService
 * @package common\services\app
 * @method array getErrors(\string $attribute)
 * @method array getFirstErrors()
 * @method array getFirstError(\string $attribute)
 * @method array getErrorSummary(\boolean $showAllErrors)
 */
class ParamsValidateService extends Component
{
    /**
     * @var ParamsValidateModel 模型
     */
    private $model = null;

    public function init()
    {
        parent::init();

        $this->model = new ParamsValidateModel();
    }

    /**
     * @param array $data 數據項
     * @param array $rules 驗證規則
     * @return bool
     */
    public function validate($data, $rules)
    {
        // 添加驗證規則
        $this->model->setRules($rules);

        // 設置參數
        $this->model->load($data, '');

        // 進行驗證
        return $this->model->validate();
    }

    public function __call($name, $params)
    {
        if ($this->model->hasMethod($name)) {
            return call_user_func_array([$this->model, $name], $params);
        } else {
            return parent::__call($name, $params);
        }
    }
}
相關文章
相關標籤/搜索