Формы
Форма — способ получить данные от посетителя: новую статью, комментарий, пароль. Ей нужны два маршрута: один показывает страницу с формой, другой принимает отправленные данные. Функции для тегов формы, вывода ошибок и прежних значений собраны в помощнике form.
Маршруты и подключение помощника
// app/Config/Routes.php
$routes->get('posts/new', 'Posts::new');
$routes->post('posts', 'Posts::create');Маршрут posts/new должен стоять выше, чем posts/(:num). Помощник form добавьте в BaseController: protected $helpers = ['form'];.
Шаблон формы
Создайте файл app/Views/posts/new.php:
<!-- app/Views/posts/new.php -->
<?= form_open('posts') ?>
<label for="title">Заголовок</label>
<input type="text" id="title" name="title">
<label for="body">Текст</label>
<textarea id="body" name="body"></textarea>
<button type="submit">Сохранить</button>
<?= form_close() ?>form_open('posts') выводит открывающий тег формы с методом POST и полным адресом /posts, form_close() — закрывающий. Поля можно писать обычным HTML.
Контроллер
// app/Controllers/Posts.php
public function new(): string
{
return view('posts/new');
}Откройте /posts/new — появится форма. Её данные принимает метод create() из прошлого урока: он проверяет поля и либо сохраняет статью, либо возвращает посетителя назад.
Защита от CSRF
CSRF — атака, при которой чужой сайт отправляет форму от имени вошедшего посетителя. Защищает от неё секретный токен в скрытом поле. Проверку включают в app/Config/Filters.php:
// app/Config/Filters.php
public array $globals = [
'before' => [
'csrf',
],
];После этого form_open() сам добавляет в форму скрытое поле с токеном, а запрос POST без него будет отклонён. В форму, написанную обычным тегом form, поле вставляют вызовом <?= csrf_field() ?>.
Вывод ошибок
После неудачной проверки контроллер возвращает посетителя вызовом redirect()->back()->withInput(). Сообщение для поля выводит validation_show_error():
<label for="title">Заголовок</label>
<input type="text" id="title" name="title">
<p class="error"><?= validation_show_error('title') ?></p>Отправьте пустую форму — под полем появится текст ошибки. Все сообщения одним списком выводит <?= validation_list_errors() ?>.
Прежние значения
Чтобы посетителю не пришлось набирать текст заново, поля заполняют функцией old():
<input type="text" id="title" name="title" value="<?= old('title') ?>">
<textarea id="body" name="body"><?= old('body') ?></textarea>old('title') возвращает значение, введённое в прошлый раз, уже экранированным. При первом открытии формы она возвращает пустоту.
Функции помощника form
| Функция | Что делает |
|---|---|
form_open('posts') | Открывающий тег формы и токен CSRF |
form_close() | Закрывающий тег |
csrf_field() | Скрытое поле с токеном |
old('title') | Прежнее значение поля |
validation_show_error('title') | Ошибка одного поля |
validation_list_errors() | Список всех ошибок |
Частая ошибка
Если вернуть посетителя через redirect()->back() без withInput(), ни old(), ни validation_show_error() ничего не выведут: значения и ошибки не были сохранены для следующего запроса. Форма просто откроется пустой, и посетитель не поймёт, что произошло.