Правила валидации, они же Rules, в модели — это набор правил, которым подчиняются данные. Например, в модели User есть поля Email, Login, Password, Name, Status при чем первые три обязательны для заполнения, логин должен состоять только из латиницы, а статус по умолчанию должен принимать значение «1». Все это можно сделать через rules.
Пример правил валидации в Yii2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| class User extends \yii\db\ActiveRecord
{
public function rules()
{
return [
['status', 'default', 'value' => 1],
['login', 'unique'],
['login', 'validateLogin'],
[['id', 'email', 'name', 'login'], 'required'],
[['password'], 'required', 'on' => 'register'],
[['id', 'status'], 'integer'],
['email', 'email'],
['name', 'string', 'max' => 64],
['name', 'trim'],
];
}
} |
class User extends \yii\db\ActiveRecord
{
public function rules()
{
return [
['status', 'default', 'value' => 1],
['login', 'unique'],
['login', 'validateLogin'],
[['id', 'email', 'name', 'login'], 'required'],
[['password'], 'required', 'on' => 'register'],
[['id', 'status'], 'integer'],
['email', 'email'],
['name', 'string', 'max' => 64],
['name', 'trim'],
];
}
}
Иногда правил валидации приходится писать много, что довольно утомительно, но здесь на помощь приходит замечательный gii, который генерирует большую часть рутинного кода. Каждое правило является массивом. Важно следить за порядком следования правил. Указывать ключи у первых двух элементов правила не следует, у последующих требуется. Первый элемент — список полей (можно задавать массивом если под правило попадается несколько полей модели, а можно просто строкой, если поле только одно).
Вторым элементом идет указание валидатора. Здесь может быть имя стандартных валидаторов Yii2 или валидаторов, написанных вами, название функции обратного вызова, выполняющей роль валидатора, или анонимная функция. Следующие элементы идут с ключами. Ключом является аргумент валидатора. Есть как общие для всех валидаторов аргументы, так и уникальные для отдельных. Разберем пример построчно:
['status', 'default', 'value' => 1], |
['status', 'default', 'value' => 1],
status |
имя атрибута |
default |
указание на стандартный валидатор DefaultValidator |
value |
аргумент валидатора, устанавливающий дефолтное значение |
Важно следить за порядком следования правил. Например, установку значения по умолчанию стоит делать до того, как будет объявление обязательных полей.
unique — стандартный валидатор UniqueValidator, проверяющий, что в БД еще нет записи с таким значением в поле. Ведь нам нужен уникальный логин.
['login', 'validateLogin'], |
['login', 'validateLogin'],
Как видно из примера, одно поле может валидироваться несколько раз.
validateLogin — это не стандартный валидатор. В данном случае указывается своя собственная функция. Сначала Yii попробует найти метод с таким названием в классе модели, потом постарается найти простую функцию с этим именем. Чтобы Yii вызвала статический метод другого класса, стоит указать в валидаторе вместо validateLogin массив с двумя элементами — имя класса и имя метода. Например так:
['login', ['Helper', 'validateLogin']], |
['login', ['Helper', 'validateLogin']],
Более подробно про собственные функции валидации расскажу чуть ниже.
[['id', 'email', 'name', 'login'], 'required'], |
[['id', 'email', 'name', 'login'], 'required'],
required — стандартный валидатор RequiredValidator, указывающий, что поля должны быть заполнены. В дополнительных аргументах не нуждается.
[['password'], 'required', 'on' => 'register'], |
[['password'], 'required', 'on' => 'register'],
Поле password было вынесено в отдельный валидатор required, потому что валидировать его стоит только при регистрации пользователя, но не при изменении его данных.
on — технически является аргументом валидатора, практически — аргументом правила. Это дополнительное условия для правила, указывающее на сценарий, при котором требуется применить валидатор. О сценариях читай ниже.
['name', 'string', 'max' => 64], |
['name', 'string', 'max' => 64],
string |
стандартный валидатор StringValidator |
max |
параметр валидатора, означающий, что длина строки не может превышать 64 символа |
Собственные функции валидации в Yii2
Если вам не подошел ни один из стандартных валидаторов, то вы можете написать свой. Есть несколько способов:
- Продвинутый — сделать полноценный класс-валидатор, унаследовав его от класса Validator. Но это слишком сложно и редко имеет смысл.
- Написать функцию валидации. Этот способ я опишу подробнее
1
2
3
4
5
6
7
| public function validateLogin($attribute)
{
if(!preg_match('/^[a-zA-Z]{3,16}$/', $this->$attribute))
{
$this->addError($attribute, 'Login incorrect');
}
} |
public function validateLogin($attribute)
{
if(!preg_match('/^[a-zA-Z]{3,16}$/', $this->$attribute))
{
$this->addError($attribute, 'Login incorrect');
}
}
Код прост до безобразия. В данном случае это метод класса модели. Имеем на входе $attribute — название поля. Проверяем значение этого поля. Если значение невалидно — генерируем ошибку.
Стоит обратить внимание, что в данном случае $attribute содержит строку с именем поля, поэтому чтобы получить значение поля, необходимо вызвать такую конструкцию: $this->attribute
Сценарии валидации в Yii2
Часто мы сталкиваемся с тем, что в одном случае нужно применить одни правила, а в другом — другие. Например регистрация, обновление профиля, восстановление пароля — это разные сценарии сохранения модели юзера. Здесь к нам на помощь приходят сценарии. Чтобы указать валидатору, что правило нужно применять только в определенных сценариях, нужно задать правилу параметр «on»:
// так
[['password'], 'required', 'on' => 'register']
// или так
[['password'], 'required', 'on' => ['register', 'change_password']] |
// так
[['password'], 'required', 'on' => 'register']
// или так
[['password'], 'required', 'on' => ['register', 'change_password']]
Кроме того, можно не указывать сценарии для каждого правила. Вместо этого можно описать сценарии в специальном методе модели:
1
2
3
4
5
6
7
8
9
10
11
| class User extends \yii\db\ActiveRecord
{
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['login'] = ['login', 'password'];
$scenarios['register'] = ['login', 'email', 'password'];
self::SCENARIO_DEFAULT => ['login', '!password']
return $scenarios;
}
} |
class User extends \yii\db\ActiveRecord
{
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['login'] = ['login', 'password'];
$scenarios['register'] = ['login', 'email', 'password'];
self::SCENARIO_DEFAULT => ['login', '!password']
return $scenarios;
}
}
Какой сценарий использовать, указывается при сохранении модели:
// так
$user = new User(['scenario' => 'register']);
// или так
$user = new User();
$user->scenario = 'register';
// или так
$user = User::findByID($id)->one();
$user->scenario = 'login'; |
// так
$user = new User(['scenario' => 'register']);
// или так
$user = new User();
$user->scenario = 'register';
// или так
$user = User::findByID($id)->one();
$user->scenario = 'login';
Условная валидация when
Атрибут правила when указывает, в каком случае нужно использовать правило. Чем-то напоминает сценарии, но не требует явного указания сценария. Значением должна быть функция обратного вызова:
// поле "name" обязательно для заполнения, только для юзера с логином "Vasya"
['name', 'required', 'when' => function($model) { return $model->login == 'Vasya'; }],
// поле "is_vampire" принимает значение "1", только если юзер регистрируется ночью
['is_vampire', 'default', 'value' => 1, 'when' => function($model) { return date('H') < = 4; }], |
// поле "name" обязательно для заполнения, только для юзера с логином "Vasya"
['name', 'required', 'when' => function($model) { return $model->login == 'Vasya'; }],
// поле "is_vampire" принимает значение "1", только если юзер регистрируется ночью
['is_vampire', 'default', 'value' => 1, 'when' => function($model) { return date('H') < = 4; }],
Условная валидация на стороне клиента whenClient
Для полного счастья следует так же добавить условие проверки и на сторону клиента. Для этого используется параметр whenClient, в который необходимо передать JS-код проверки.
['name', 'required', 'whenClient' => "function (attribute, value) {return $('#login').value == 'Vasya';}"], |
['name', 'required', 'whenClient' => "function (attribute, value) {return $('#login').value == 'Vasya';}"],
Естественно, условие будет автоматически добавлено только при условии использования функционала Yii для создания форм.
SkipOnEmpty
Указывает валидатору пропускать или не пропускать правило, если значение поля пустое. По умолчанию true (то есть пропускать).
SkipOnError
Указывает валидатору пропускать или не пропускать правило, в предыдущих правилах для этого поля уже была ошибка. По умолчанию true (то есть пропускать).
Добавить комментарий