Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Формы с ActiveForm

ActiveForm — виджет, который строит форму HTML по модели: сам создаёт поля с подписями, показывает ошибки проверки и добавляет защиту от подделки запросов. Виджетом в Yii называют готовый блок интерфейса, который вызывают в шаблоне.

Действие контроллера

Одно действие и показывает форму, и принимает её. Добавьте в controllers/PostController.php:

// controllers/PostController.php
public function actionCreate()
{
    $post = new Post();
 
    if ($post->load(Yii::$app->request->post()) && $post->save()) {
        return $this->redirect(['post/view', 'id' => $post->id]);
    }
 
    return $this->render('create', ['post' => $post]);
}

load() заполняет модель данными формы и возвращает false, если форма не отправлена. save() проверяет и записывает. При успехе посетитель уходит на страницу статьи, иначе форма показывается снова — уже с ошибками.

Шаблон формы

Создайте файл views/post/create.php:

<?php
// views/post/create.php
 
use yii\helpers\Html;
use yii\widgets\ActiveForm;
 
$this->title = 'Новая статья';
?>
 
<h1><?= Html::encode($this->title) ?></h1>
 
<?php $form = ActiveForm::begin(); ?>
 
<?= $form->field($post, 'title') ?>
<?= $form->field($post, 'body')->textarea(['rows' => 8]) ?>
 
<?= Html::submitButton('Сохранить', ['class' => 'btn btn-primary']) ?>
 
<?php ActiveForm::end(); ?>

Откройте /post/create. Вызов field() создаёт подпись из attributeLabels(), поле ввода и место для ошибки. Отправьте пустую форму — под полями появятся сообщения из правил модели. В стандартном проекте можно подключить yii\bootstrap5\ActiveForm вместо yii\widgets\ActiveForm — форма получит оформление Bootstrap.

Столбцы user_id, created_at и updated_at пока не заполняются. До урока о поведениях задайте их в действии перед save() или дайте им значения по умолчанию в миграции.

Виды полей

ВызовПоле
$form->field($post, 'title')Текстовая строка
->textarea(['rows' => 8])Многострочный текст
->passwordInput()Пароль
->dropDownList([0 => 'Черновик', 1 => 'Опубликована'])Выпадающий список
->checkbox()Флажок
->hint('До 255 символов')Подсказка под полем
->label('Название')Своя подпись

Изменение записи

Форма изменения отличается только тем, что модель берут из базы:

public function actionUpdate(int $id)
{
    $post = Post::findOne($id);
 
    if ($post === null) {
        throw new NotFoundHttpException('Статья не найдена.');
    }
 
    if ($post->load(Yii::$app->request->post()) && $post->save()) {
        return $this->redirect(['post/view', 'id' => $post->id]);
    }
 
    return $this->render('update', ['post' => $post]);
}

Поля окажутся заполненными текущими значениями. Чтобы не повторять разметку, поля выносят в общий файл views/post/_form.php и вставляют его в create.php и update.php вызовом $this->render('_form', ['post' => $post]).

Защита от подделки запросов

ActiveForm добавляет в форму скрытое поле _csrf со случайным значением. Yii сверяет его при каждом запросе POST и отклоняет формы, отправленные с чужих сайтов.

Частая ошибка

Форма, написанная тегами вручную, отправляет поля с именами вроде title. А load() ждёт данные, сгруппированные по имени модели: Post[title], Post[body]. Такая форма «не сохраняется» без единой ошибки. Стройте поля через $form->field() — имена получатся правильными.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.