代码之家  ›  专栏  ›  技术社区  ›  mrateb

yii2-验证嵌套对象

  •  0
  • mrateb  · 技术社区  · 6 年前

    这是一个关于我思考了一段时间的话题的问题。

    在yii2中,通常建议为您的请求创建表单模型。将规则添加到这些模型中以验证输入。例如yii2指南中的entryform

    <?php
    
    namespace app\models;
    
    use Yii;
    use yii\base\Model;
    
    class EntryForm extends Model
    {
        public $name;
        public $email;
    
        public function rules()
        {
            return [
                [['name', 'email'], 'required'],
                ['email', 'email'],
            ];
        }
    }
    

    我的问题是,当我们有嵌套对象时。示例是用于创建 顾客 有多个 分支机构 . 如果 顾客 分公司 是两个独立的模型,但都以一种形式提交,验证来自这样一个嵌套形式的输入的最佳选择是什么。记住这里的输入是嵌套的。例子:

    {
      "name": "customer",
      "vat_no": "12345678",
      "time_zone": 277,
      "category": 1,
      "email": "customer@mycustomer.com",
      "stores":[
        {
            "name": "store1",
            "phone": 1234567
        },
        {
            "name": "store2",
            "phone": 2345678
        }
    ]
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   rob006    6 年前

    对于简单的情况,可以在表单模型中使用一个模型和自定义验证器:

    public function rules() {
        return [
            // ...
            ['stores', 'validateStores'],
        ];
    }
    
    public function validateStores() {
        $phoneValidator = new StringValidator(); // use real validators
        $nameValidator = new StringValidator(); // use real validators
        foreach ($this->stores as $store) {
            if (!$phoneValidator->validate($store['phone'], $error)) {
                $this->addError('stores', $error);
                return; // stop on first error
            }
            if (!$nameValidator->validate($store['name'], $error)) {
                $this->addError('stores', $error);
                return; // end on first error
            }
        }
    }
    

    validateStores() 可以提取到单独的验证器类,然后您也可以使用 EachValidator 而不是 foreach .


    对于更复杂的嵌套模型,您可能应该创建单独的 StoreForm 存储的模型(因此您将拥有嵌套的表单模型),并调用 validate() 关于孩子。

    /**
     * @var StoreForm[]
     */
    public $stores;
    
    public function rules() {
        return [
            // ...
            ['stores', 'validateStores'],
        ];
    }
    
    public function validateStores() {
        foreach ($this->stores as $store) {
            if (!$store->validate()) {
                $this->addError('stores', 'Stores config is incorrect.');
                return;
            }
        }
    }