Формы и валидация в Yii 2: что нужно знать до начала
Как собрать рабочую форму в Yii 2 с проверкой данных на сервере: модель, правила валидации, вывод ошибок и защита от CSRF. Разбор для тех, кто открывает фреймворк впервые.

К концу этого материала у вас будет форма обратной связи на Yii 2, которая проверяет введённые данные, показывает ошибки прямо под полями и не пропускает пустой email. На сборку уйдёт примерно 30–40 минут, если PHP и Composer уже стоят. Главное, что вы вынесете: в Yii валидация живёт не в контроллере и не в шаблоне, а в модели — и пока вы не примете это как данность, будете бороться с фреймворком вместо того, чтобы пользоваться им.
Что нужно иметь до начала
Проверьте, что всё на месте, до того как писать первую строку. Иначе узнаете о нехватке на середине.
- PHP 7.4 или новее. Yii 2.0.x работает и на 7.4, но живые проекты сейчас на PHP 8.1–8.3. Версию проверяет команда
php -v. - Composer. Yii ставится через него, вручную распаковывать архивы не нужно.
- Установленное приложение Yii 2. Базовый шаблон ставится командой
composer create-project yiisoft/yii2-app-basic myapp. Дальше все пути в статье — относительно папкиmyapp. - Работающий веб-сервер. Для проверки хватит встроенного:
php yii serveподнимет сайт наhttp://localhost:8080.
Речь про Yii 2.0.x — самую распространённую ветку. Yii 3 существует, но это другой фреймворк с другим API, и материал к нему не подходит.
Где в Yii живёт валидация
Три вещи, которые ломают новичкам картину мира.
Первое. Данные формы описывает не HTML, а PHP-класс — модель. Модель хранит поля, знает правила их проверки и понимает, какие сообщения об ошибке показать. HTML только рисует то, что модель уже описала.
Второе. Валидация по умолчанию серверная. Атрибут required в браузере тут ни при чём: проверку выполняет метод модели после отправки. Клиентская проверка в Yii тоже есть — виджет ActiveForm генерирует её сам на основе тех же правил, — но полагаться только на неё нельзя, её обходят отключением JavaScript.
Третье. Правила задаются в одном методе rules(). Не разбросаны по коду, не в аннотациях — один массив, который читается сверху вниз.
Правило Yii: если вы проверяете данные формы в контроллере черезifиempty()— вы пишете не на Yii, а на голом PHP внутри Yii. Всё, что можно, выносите вrules().
Шаг за шагом: форма обратной связи
1. Модель формы
Создайте файл models/ContactForm.php. В базовом шаблоне такой класс уже есть — тогда сверьте его с примером ниже.
<?php
namespace app\models;
use yii\base\Model;
// Модель формы наследуется от Model, а не от ActiveRecord:
// за формой нет таблицы в базе
class ContactForm extends Model
{
public $name;
public $email;
public $body;
// Правила проверки полей
public function rules()
{
return [
// name и email обязательны
[['name', 'email'], 'required'],
// email должен быть корректным адресом
['email', 'email'],
// ограничение длины имени
['name', 'string', 'max' => 128],
// тело письма — необязательное, но строка
['body', 'string'],
];
}
// Понятные подписи полей вместо имён переменных
public function attributeLabels()
{
return [
'name' => 'Ваше имя',
'email' => 'Email для ответа',
'body' => 'Сообщение',
];
}
}
Проверка: файл сохранён, класс называется так же, как файл, namespace — app\models. Ошибка в namespace даст «Class not found» на следующем шаге.
2. Действие контроллера
В controllers/SiteController.php добавьте или откройте метод actionContact().
public function actionContact()
{
$model = new \app\models\ContactForm();
// load() забирает данные из POST и раскладывает по полям модели
// validate() прогоняет все правила из rules()
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
// сюда попадаем только если данные прошли проверку
Yii::$app->session->setFlash('contactSuccess', 'Сообщение отправлено.');
return $this->refresh();
}
// и при первом открытии, и при ошибках валидации
// отдаём ту же форму — с ошибками, если они есть
return $this->render('contact', ['model' => $model]);
}
Ключевой момент — связка load() && validate(). Метод load() возвращает false, если POST пустой (форму ещё не отправляли), и до validate() дело не доходит. Если данные пришли, но не прошли проверку, validate() вернёт false и заполнит модель ошибками.
Проверка: откройте /index.php?r=site/contact. Пустая форма должна открыться без сообщения об ошибке.
3. Шаблон с ActiveForm
Создайте views/site/contact.php. Виджет ActiveForm сам подставит подписи, выведет ошибки и добавит скрытое поле с CSRF-токеном.
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php if (Yii::$app->session->hasFlash('contactSuccess')): ?>
<div class="alert alert-success">
<?= Yii::$app->session->getFlash('contactSuccess') ?>
</div>
<?php endif; ?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'name') ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'body')->textarea(['rows' => 6]) ?>
<div class="form-group">
<?= Html::submitButton('Отправить', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Каждый $form->field() рисует подпись, поле ввода и место под сообщение об ошибке. Ошибку туда кладёт validate() — руками её выводить не нужно.
Проверка: отправьте форму с пустым именем. Под полем «Ваше имя» появится красная надпись «Необходимо заполнить «Ваше имя».» Введите в email слово без собаки — получите ошибку формата. Заполните всё верно — увидите зелёное сообщение об отправке.
Частые правила валидации
Валидаторов в Yii больше двух десятков. Вот те, что нужны почти в каждой форме.
| Валидатор | Что проверяет | Пример правила |
|---|---|---|
required | Поле не пустое | [['name'], 'required'] |
email | Корректный адрес | ['email', 'email'] |
string | Строка, длина через min/max | ['name', 'string', 'max' => 128] |
integer | Целое число | ['age', 'integer'] |
number | Число, в том числе дробное | ['price', 'number'] |
in | Значение из списка | ['status', 'in', 'range' => [0, 1, 2]] |
compare | Сравнение с другим полем | ['passwordRepeat', 'compare', 'compareAttribute' => 'password'] |
match | Совпадение с регулярным выражением | ['phone', 'match', 'pattern' => '/^\+7\d{10}$/'] |
Точные имена параметров и полный список сверяйте в разделе Core Validators документации — там же указаны значения по умолчанию для каждого.
Про CSRF: почему форма может «молча не работать»
Yii по умолчанию требует CSRF-токен во всех POST-запросах. Виджет ActiveForm добавляет скрытое поле с токеном автоматически — поэтому форму собирают именно через него, а не голым HTML.
Если напишете тег <form method="post"> руками и забудете токен, отправка вернёт ошибку 400 «Bad Request: Unable to verify your data submission.» Не отключайте CSRF, чтобы «починить» — вставьте токен через Html::csrfMetaTags() или, что проще, используйте ActiveForm.
Если не получилось
- «Class 'app\models\ContactForm' not found». Namespace в файле модели не совпадает с путём, либо опечатка в имени класса. Проверьте, что файл лежит в
models/и namespace —app\models. - Форма отправляется, но ошибки не показываются, а данные не проходят. Скорее всего вы вызвали
validate(), но рисуете поля не через$form->field(), а обычнымиHtml::input(). Тогда некуда положить сообщение — используйтеfield(). - Bad Request (#400) «Unable to verify your data submission». Нет CSRF-токена. Собирайте форму через
ActiveForm, а не вручную. - Данные не попадают в модель,
load()возвращает true, но поля пустые. Имена полей в POST должны идти какContactForm[name].ActiveFormделает это сам; при ручной вёрстке имя формируется по короткому имени класса модели. - Валидатор молчит на несуществующем поле. Правило для атрибута, которого нет как public-свойства модели, просто игнорируется. Объявите свойство в классе.
Что делать дальше
Когда базовая форма работает, двигайтесь по порядку:
- Добавьте сценарии (
scenarios()), если одни и те же поля проверяются по-разному при регистрации и редактировании. - Разберитесь с кастомными валидаторами — методом-функцией прямо в модели, когда встроенных правил не хватает.
- Посмотрите, как связать форму с базой через
ActiveRecord: там та же логикаrules()иvalidate(), но модель уже умеет сохраняться в таблицу.
Клиентская и AJAX-валидация — отдельная тема; здесь разобрана только серверная проверка, на которой всё держится.
Инфобез и 152-ФЗ: Аудит политик конфиденциальности, правила сбора cookie.
Спросить за 20 ₽Источники: Yii 2 Guide — Validating Input, Yii 2 Guide — Core Validators
Частые вопросы
Форму нужно наследовать от Model или ActiveRecord?
У меня другая версия — Yii 3. Этот код подойдёт?
Валидация в браузере проходит, но пустые данные всё равно сохраняются. Почему?
Как показать своё сообщение об ошибке вместо стандартного?
Можно ли проверить одно поле по нескольким условиям?
Что будет, если я забуду объявить public-свойство для поля из rules()?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.