29Встроенные валидаторы
Справочник валидаторов ядра — required, string, integer/number, email, url, ip, date, compare, in, match, boolean, default, filter, trim, each, exist, unique, file, image, captcha, safe — с ключевыми опциями и типичными примерами.
Каждый валидатор — класс в yii\validators, но в rules() его зовут коротким именем. Ниже — все встроенные, сгруппированные по назначению, с опциями, которые реально нужны. Общие для всех: message, on, except, skipOnEmpty, skipOnError, when, whenClient, enableClientValidation.
Обязательность и умолчания#
requiredrequiredValue (ожидать конкретное значение), strict (сравнивать строго). Один из двух проверяющих валидаторов (второй — captcha), который срабатывает и на пустом значении; у default, filter и trim skipOnEmpty тоже выключен, но они не проверяют, а меняют значениеdefaultvalue (значение или замыкание), если атрибут пуст. Не проверяет, а заполняетsafe[['username', 'password'], 'required'],
['accept', 'required', 'requiredValue' => 1, 'message' => 'Примите условия'],
['age', 'default', 'value' => null],
['country', 'default', 'value' => 'USA'],
['from', 'default', 'value' => function ($model) { return date('Y-m-d'); }],
['notes', 'safe'],Строки и форматы#
stringmin..max или ровно length; encoding (по умолчанию charset приложения)emailallowName (разрешить Иван <ivan@site.ru>), checkDNS (проверить MX-запись), enableIDNurlvalidSchemes (['http', 'https']), defaultScheme (дописать, если схемы нет), enableIDNipipv4, ipv6, subnet (true — обязательно с маской, null — можно с маской), normalize, ranges (белый/чёрный список: ['10.0.1.0/24', '!10.0.0.0/8', 'any']), negation (разрешить !)matchpattern; not — инвертироватьtrimchars — какие символыfilterfilter (строка, замыкание, [класс, метод]); skipOnArray — не применять к массивам['username', 'string', 'length' => [4, 24]],
['email', 'email', 'checkDNS' => true],
['website', 'url', 'defaultScheme' => 'https'],
['ip', 'ip', 'ipv6' => false, 'ranges' => ['10.0.0.0/8', '!any']],
['username', 'match', 'pattern' => '/^[a-z]\w*$/i'],
['username', 'match', 'pattern' => '/^admin$/', 'not' => true, 'message' => 'Имя занято'],
[['title', 'body'], 'trim'],
['username', 'filter', 'filter' => 'strtolower'],
['phone', 'filter', 'filter' => function ($value) { return preg_replace('/\D/', '', $value); }],ip при subnet => null и normalize => true приведёт 192.168.1.1 к 192.168.1.1/32; при expandIPv6 — развернёт сокращённую запись.
Числа и логика#
integermin, max, tooSmall, tooBignumber (double)min/max; integerPattern, numberPatternbooleantrueValue/falseValue (по умолчанию 1/0), strict. Не преобразует значениеcomparecompareAttribute или значением compareValue; operator (==, ===, !=, !==, >, >=, <, <=); type — как сравнивать: string (по умолчанию: оба значения приводятся к строке и сравниваются операторами PHP) или number (приводятся к float)inrange; strict, not, allowArray (проверить каждый элемент массива)['age', 'integer', 'min' => 18],
['price', 'number', 'min' => 0, 'max' => 1e6],
['salary', 'double'],
['remember_me', 'boolean'],
['is_active', 'boolean', 'trueValue' => true, 'falseValue' => false, 'strict' => true],
['password_repeat', 'compare', 'compareAttribute' => 'password'],
['age', 'compare', 'compareValue' => 30, 'operator' => '>=', 'type' => 'number'],
['level', 'in', 'range' => [1, 2, 3]],
['tags', 'in', 'range' => ['php', 'yii'], 'allowArray' => true],Даты#
dateformat (ICU: yyyy-MM-dd, или php:Y-m-d); timestampAttribute — куда записать UNIX-время; timestampAttributeFormat — или в каком формате записать; min/max (+tooSmall/tooBig); timeZone, localedatetime, timetype => 'datetime' / 'time' (короткие имена — с 2.0.10)[['from_date', 'to_date'], 'date'],
['birthday', 'date', 'format' => 'php:d.m.Y', 'timestampAttribute' => 'birthday_ts'],
['created', 'datetime', 'format' => 'php:Y-m-d H:i:s',
'timestampAttribute' => 'created', 'timestampAttributeFormat' => 'php:Y-m-d H:i:s'],
['start', 'date', 'min' => date('Y-m-d'), 'tooSmall' => 'Дата уже прошла'],Без format берётся dateFormat компонента formatter. С timestampAttribute проверенное значение преобразуется в UNIX-timestamp и записывается в атрибут (можно в тот же самый) — удобно для сохранения в INT.
Массивы и вложенность#
eachrule к каждому элементу массива; allowMessageFromRule (сообщение от вложенного правила), stopOnFirstError['categoryIDs', 'each', 'rule' => ['integer']],
['emails', 'each', 'rule' => ['email'], 'allowMessageFromRule' => false, 'message' => 'Один из адресов неверен'],Проверяет только один уровень; для сложных структур — свой валидатор. Не работает с unique/exist через targetAttribute.
Проверки по базе данных#
existtargetClass (по умолчанию — класс модели), targetAttribute (столбец или карта ['a1' => 'b1']), filter (доп. условие), allowArray, targetRelation (по связи AR, 2.0.14)uniquecomboNotUnique (сообщение для составного ключа). Для AR исключает саму запись при обновлении['a1', 'exist'], // столбец a1 в таблице модели
['category_id', 'exist', 'targetClass' => Category::class, 'targetAttribute' => 'id'],
// пара (a1, a2) должна существовать; ошибка — только у a1
['a1', 'exist', 'targetAttribute' => ['a1', 'a2']],
// значение a2 ищется в столбце a1: [атрибут модели => столбец таблицы]
['a1', 'exist', 'targetAttribute' => ['a2' => 'a1']],
['a1', 'exist', 'filter' => ['status' => 1]],
['user_id', 'exist', 'targetRelation' => 'user'],
['username', 'unique'],
['email', 'unique', 'targetClass' => User::class, 'filter' => ['status' => User::STATUS_ACTIVE]],
[['slug', 'lang'], 'unique', 'targetAttribute' => ['slug', 'lang']], // комбинация уникальнаОба не имеют клиентской реализации — используйте AJAX-валидацию.
Файлы и изображения#
fileUploadedFile: extensions, mimeTypes (image/*, text/plain), minSize, maxSize, maxFiles (0 — без ограничения), checkExtensionByMimeType (сверять расширение с реальным MIME, по умолчанию true), wrongExtension, tooBig, tooMany…imagefile + проверка изображения: minWidth, maxWidth, minHeight, maxHeight, notImage, underWidth, overWidth…['file', 'file', 'extensions' => ['pdf', 'docx'], 'maxSize' => 5 * 1024 * 1024, 'skipOnEmpty' => false],
['avatar', 'image', 'extensions' => 'png, jpg', 'minWidth' => 100, 'maxWidth' => 1000, 'minHeight' => 100],
['docs', 'file', 'maxFiles' => 10],Помните про upload_max_filesize/post_max_size в php.ini и enctype="multipart/form-data" — подробнее в разделе Формы.
CAPTCHA#
captchayii\captcha\Captcha; captchaAction (по умолчанию site/captcha), caseSensitive. Как и required, работает с пустым значением — пустое поле сразу даёт ошибку// модель
['verifyCode', 'captcha'],
// контроллер: действие captcha в actions()
'captcha' => ['class' => 'yii\captcha\CaptchaAction', 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null],
// форма
<?= $form->field($model, 'verifyCode')->widget(Captcha::class) ?>Требует расширения GD или ImageMagick с поддержкой FreeType.
Сводка по ключевым опциям#
| Валидатор | Самое важное |
|---|---|
required | requiredValue, strict |
string | min, max, length |
integer, number | min, max |
email, url | checkDNS / defaultScheme, enableIDN |
compare | compareAttribute, operator, type |
in | range, not, allowArray |
date | format, timestampAttribute, min, max |
each | rule |
exist, unique | targetClass, targetAttribute, filter |
file, image | extensions, maxSize, maxFiles, minWidth… |
match | pattern, not |
filter, trim, default | filter / chars / value — меняют значение |
required и captcha; остальные проверяющие пропускают пустые атрибуты, пока не указан 'skipOnEmpty' => false. У default, filter и trim он тоже выключен, но они не проверяют, а меняют значение.
Записывает в указанный атрибут UNIX-время (или строку в timestampAttributeFormat), полученное из проверенной даты.
Когда значения — не просто числа. Сравнение по умолчанию строковое, и '2024-1-5' > '2024-01-10' оказывается истиной. Для чисел задайте 'type' => 'number', для дат сравнивайте UNIX-время из timestampAttribute.
['ids', 'each', 'rule' => ['integer']].
Правилом ['attr', 'safe'].