如果您查看 yii\validators\EachValidator 源代码,rule 内部验证器中的 when 属性从未被调用:
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;}]]