Yii2. Свой валидатор
В посте про валидацию в Yii2 я коснулась основ валидации и дала краткое описание встроенных валидаторов. Но что, если ни один из них нам не подходит. В этом случае мы можем написать свой.
Есть три способа реализации своего валидатора:
В такой постановке нам не подходят валидаторы exist и unique, потому что первый проверяет только на существование (и даже параметр filter нам не поможет), а второй на уникальность в рамках всего справочника.
Есть три способа реализации своего валидатора:
- написать inline-функцию для валидации;
- реализовать метод в модели с именем вашего валидатора;
- реализовать класс, унаследованный от Validator.
В такой постановке нам не подходят валидаторы exist и unique, потому что первый проверяет только на существование (и даже параметр filter нам не поможет), а второй на уникальность в рамках всего справочника.
Inline-функция
public function rules()
{
return [
['serial_number', function ($attribute, $params) {
if ($this->type_id) {
$existModel = Type::find()->byType($this->type_id)->bySerialNumber($this->$attribute)->one();
if ($existModel) {
$this->addError($attribute, 'Serial number must be unique for type.');
}
}
}
],
];
}
Метод модели
public function rules()
{
return [
['serial_number', 'uniqueByType']
];
}
public function uniqueByType($attribute, $params) {
if ($this->type_id) {
$existModel = Type::find()->byType($this->type_id)->bySerialNumber($this->$attribute)->one();
if ($existModel) {
$this->addError($attribute, 'Serial number must be unique for type.');
}
}
}
Класс Validator
В этом примере есть одно отличие – я добавила параметр compare, в котором можно задать наименование атрибута типа запчасти. Обратите внимание, что в этом примере я опустила необходимые проверки (например, что параметр compare вообще задан).use \yii\validators\Validator;
class UniqueByTypeValidator extends Validator
{
public $compare;
public function validateAttribute($model, $attribute)
{
$compare = $this->compare;
if ($this->$compare) {
$existModel = Type::find()->byType($this->$compare)->bySerialNumber($this->$attribute)->one();
if ($existModel) {
$this->addError($attribute, 'Serial number must be unique for type.');
}
}
}
}
Посты по теме:
Yii2: встроенные валидаторы. Описание, параметры
Yii2: валидация, правила валидации, встроенные валидаторы
лайк, что тут скажешь... Коротко по делу. Редкость
ОтветитьУдалить+
УдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьДоходчиво, просто. Замечательно! Забрал в инструменты (это, то место, которым постоянно пользуешься, если с памятью твоей - встала). :-)
ОтветитьУдалитьчто проверяется в строке
ОтветитьУдалитьif ($this->type_id) {
Как описано в примере: У каждой запчасти есть тип. Соответственно, строится запрос на поиск других запчастей в справочнике с таким же типом (type_id) и серийным номером (serial_number). Если будет найдена хоть одна запись ($existModel) - значит серийный номер в рамках этого типа не уникален.
УдалитьДобрый день!
ОтветитьУдалитьМогли бы подсказать что имеется ввиду под Type:: если у меня в правилах
public function rules()
{
return [
....
['password', 'validatePassword'],
];
}
Type - модель типов запчастей
УдалитьЗдравствуйте. У меня такая ситуация. Я упаковал работу с большой формой в 1 модель формы. Форма пишет данные в 4 таблицы. При этом для каждой таблицы я использую отдельную модель. Модель каждой таблицы я использую в модели формы, с которой я и работаю. Валидация полей проходит в модели формы, но так как она не связана с таблицами в бд, а лишь посредник, в ней не работает валидация по unique. Хочу написать свою, но не знаю как:
ОтветитьУдалить1. Определять динамически таблицу и поле, в которых нужно проверять. Например, [['number_k', 'organization_id'], 'unique'], если поля number_k и organization_id в разных таблицах. Как в своей функции валидации определить с каких они таблиц и вообще получить сами названия полей в своей функции?
Или может есть более интересный способ?
Почему-то не определяет почту. Буду очень рад ответу buttalbakl@gmail.com
УдалитьПример использование внешнего валидатора:
ОтветитьУдалить['from', DateTimeValidator::class],