Search code examples
validationyii2modelsrules

Why is Yii2 using arrays for rules instead of objects?


Rules in Yii2 models look like this:

[
    // checks if "level" is 1, 2 or 3
    ['level', 'in', 'range' => [1, 2, 3]],
]

Wouldn't it be better if they were objects like this?

[
  new RangeRule('level', [1, 2, 3])
]

Solution

  • You can use validator objects like this:

    use yii\validators\Validator;
    use yii\validators\NumberValidator;
    use yii\validators\StringValidator;
    
    class TestModel extends \yii\base\Model
    {
        public $firstProperty;
        public $secondProperty;
    
        public function rules()
        {
            return [
                new NumberValidator(['attributes' => ['firstProperty'], 'integerOnly' => true, 'min' => 0, 'max' => 100]),
                new StringValidator(['attributes' => ['secondProperty'], 'max' => 5]),
            ];
        }
    }
    

    Moreover, you can decorate these objects as you want (using additional classes and methods):

    class TestModel extends \yii\base\Model
    {
        public $firstProperty;
        public $secondProperty;
    
        public function rules()
        {
            // Prepare Int validator
            $validatorInt              = new NumberValidator();
            $validatorInt->integerOnly = true;
            $validatorInt->min         = 0;
            $validatorInt->max         = 100;
    
            // Prepare String validator
            $validatorString      = new StringValidator();
            $validatorString->max = 5;
    
            // Make rules
            return [
                static::_makeRule(['firstProperty'], $validatorInt),
                static::_makeRule(['secondProperty'], $validatorString),
            ];
        }
    
        protected function _makeRule($attrName, Validator $validatorObj)
        {
            $validatorObj = clone $validatorObj;
    
            $validatorObj->attributes = (array)$attrName;
    
            $validatorObj->init();                          // Initializes validator and normalizes values
    
            return $validatorObj;
        }
    
    }