Если вы посмотрите на yii \ validators \ EachValidator source, when
атрибут из валидатора внутри rule
, так и не был вызван:
if (!$validator->skipOnEmpty || !$validator->isEmpty($v)) {
$validator->validateAttribute($model, $attribute);
}
Сравните это с его родителемclass 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;}]]