在嵌套yii2 EachValidator中使用“ when”

时间:2019-02-20 19:54:59

标签: php yii2 yii2-validation

是否可以在嵌套的EachValidator中使用 when 属性? 这是我的规则,但不起作用:

[['list'], 'each', 'rule' => ['required', 'when' => function ($model) {return false;}, 'whenClient' => "function (attribute, value) {return false;}"]],

我想测试在某种情况下是否可以避免所需的验证。 因此,要进行测试,我总是说 return false 。 这只是一个测试返回语句,以验证其是否有效。

1 个答案:

答案 0 :(得分:0)

如果您查看yii\validators\EachValidator的源代码,则不会调用when内部的验证器的rule属性:

if (!$validator->skipOnEmpty || !$validator->isEmpty($v)) {
    $validator->validateAttribute($model, $attribute);
}

将其与父类yii\validators\Validator进行比较:

foreach ($attributes as $attribute) {
    $skip = $this->skipOnError && $model->hasErrors($attribute)
        || $this->skipOnEmpty && $this->isEmpty($model->$attribute);
    if (!$skip) {
        if ($this->when === null || call_user_func($this->when, $model, $attribute)) {
            $this->validateAttribute($model, $attribute);
        }
    }
}

一种实现目标的方法是扩展yii\validators\EachValidator并覆盖其validateAttribute($model, $attribute)方法(以及私有属性和在此定义的方法):

/**
 * @var Validator validator instance.
 */
private $_validator;

/**
 * Returns the validator declared in [[rule]].
 * @param Model|null $model model in which context validator should be created.
 * @return Validator the declared validator.
 */
private function getValidator($model = null)
{
    // same as in parent
}

/**
 * Creates validator object based on the validation rule specified in [[rule]].
 * @param Model|null $model model in which context validator should be created.
 * @throws \yii\base\InvalidConfigException
 * @return Validator validator instance
 */
private function createEmbeddedValidator($model)
{
    // same as in parent
}

/**
 * {@inheritdoc}
 */
public function validateAttribute($model, $attribute)
{
    ... // same as in parent
    foreach ($value as $k => $v) {
        $model->clearErrors($attribute);
        $model->$attribute = $v;
        // start override original code
        $skip = $validator->skipOnEmpty && $validator->isEmpty($v);
        if (!$skip) {
            if ($validator->when === null || call_user_func($validator->when, $model, $attribute)) {
                $validator->validateAttribute($model, $attribute);
            }
        }
        // end override original code
        $filteredValue[$k] = $model->$attribute;
        if ($model->hasErrors($attribute)) {
            ... // same as in parent
        }
    }
    ... // same as in parent
}

像这样在rules()中使用自定义类:

[['list'], \app\models\EachValidator::className(), 'rule' => ['required', 'when' => function ($model) {return false;}]]