Создание и редактирование записей
Прекрасно! У нас есть суперклассный новый блог, люди активно спорят в комментариях, и у нас наконец появилось время ещё попрограммировать. Хотя Adminer – отличный инструмент, писать в нём новые записи блога не слишком удобно. Пожалуй, самое время создать простую форму для добавления новых записей прямо из приложения. Сделаем это.
Начнём с проектирования пользовательского интерфейса:
- На главную страницу добавим ссылку “Написать новую запись”.
- Эта ссылка покажет форму с полем заголовка и текстовой областью для содержимого записи.
- Когда мы нажмём кнопку Сохранить, запись сохранится в базу данных.
Позже мы добавим ещё и аутентификацию и разрешим добавлять новые записи только вошедшим пользователям. Но это сделаем потом. Какой код нам нужно написать сейчас, чтобы всё заработало?
- Создать новый презентер с формой для добавления записей.
- Определить callback, который будет вызван после успешной отправки формы и сохранит новую запись в базу данных.
- Создать новый шаблон для формы.
- Добавить ссылку на форму в шаблон главной страницы.
Новый презентер
Назовём новый презентер EditPresenter и сохраним его в
app/Presentation/Edit/EditPresenter.php. Ему тоже нужно подключиться к базе
данных, так что и здесь мы напишем конструктор, требующий соединение с
базой данных:
<?php
namespace App\Presentation\Edit;
use Nette;
use Nette\Application\UI\Form;
final class EditPresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
}
Форма для сохранения записей
Формы и компоненты мы уже разбирали, когда добавляли поддержку комментариев. Если что-то ещё неясно, сходите повторить, как работают формы и компоненты, мы тут подождём ;)
Теперь добавьте в EditPresenter этот метод:
protected function createComponentPostForm(): Form
{
$form = new Form;
$form->addText('title', 'Заголовок:')
->setRequired();
$form->addTextArea('content', 'Содержимое:')
->setRequired();
$form->addSubmit('send', 'Сохранить и опубликовать');
$form->onSuccess[] = $this->postFormSucceeded(...);
return $form;
}
Сохранение новой записи из формы
Продолжим добавлением метода-обработчика:
private function postFormSucceeded(array $data): void
{
$post = $this->database
->table('posts')
->insert($data);
$this->flashMessage('Запись успешно опубликована.', 'success');
$this->redirect('Post:show', $post->id);
}
Коротко о том, что здесь происходит: он берёт значения из формы, вставляет их в базу данных, создаёт для пользователя сообщение о том, что запись успешно сохранена, и перенаправляет на страницу, где эта запись опубликована, чтобы вы могли увидеть, как она выглядит.
Страница для создания новой записи
Теперь создадим шаблон Edit/create.latte:
{block content}
<h1>Новая запись</h1>
{control postForm}
Всё уже должно быть понятно. Последняя строка отрисовывает форму, которую мы только что создали.
Мы могли бы создать и соответствующий метод renderCreate(), но это не
обязательно. Нам не нужно получать никаких данных из базы данных и
передавать их в шаблон, так что метод был бы пустым. В таких случаях
метод может вообще не существовать.
Ссылка на создание записей
Вы, наверное, уже знаете, как добавить ссылку на EditPresenter и его
действие create. Попробуйте.
Достаточно добавить в файл app/Presentation/Home/default.latte следующее:
<a n:href="Edit:create">Написать новую запись</a>
Редактирование записей
Теперь добавим возможность редактировать существующие записи. Это
будет совсем просто. У нас уже есть форма postForm, и мы можем
использовать её и для редактирования.
Добавим в EditPresenter новую страницу edit:
public function renderEdit(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Запись не найдена');
}
$this->getComponent('postForm')
->setDefaults($post->toArray());
}
И создадим соответствующий шаблон Edit/edit.latte:
{block content}
<h1>Редактирование записи</h1>
{control postForm}
И обновим метод postFormSucceeded, который сможет либо добавить новую
запись (как сейчас), либо отредактировать существующую:
private function postFormSucceeded(array $data): void
{
$id = $this->getParameter('id');
if ($id) {
$post = $this->database
->table('posts')
->get($id);
$post->update($data);
} else {
$post = $this->database
->table('posts')
->insert($data);
}
$this->flashMessage('Запись успешно опубликована.', 'success');
$this->redirect('Post:show', $post->id);
}
Когда параметр id задан, это значит, что запись редактируется. В
таком случае мы проверим, что запись действительно существует, и если
так, обновим её в базе данных. Если id не задан, значит, нужно
добавить новую запись.
Но откуда берётся id? Это параметр, передаваемый методу
renderEdit.
Теперь вы можете добавить ссылку в шаблон app/Presentation/Post/show.latte:
<a n:href="Edit:edit $post->id">Редактировать эту запись</a>
Итоги
Блог работает, люди бойко комментируют, и для добавления новых записей нам больше не нужен Adminer. Он полностью самостоятелен, и публиковать в нём могут даже обычные люди. Но постойте, вряд ли это нормально, что кто угодно, то есть буквально кто угодно в интернете, может публиковать в нашем блоге. Нужна какая-то аутентификация, чтобы публиковать могли только вошедшие пользователи. Её мы добавим в следующей главе.