Создание и редактирование постов
Это здорово! У нас есть супер крутой новый блог, люди активно обсуждают в комментариях, и у нас наконец-то есть немного времени на дальнейшее программирование. Хотя Adminer — отличный инструмент, он не совсем идеален для написания новых постов в блог. Вероятно, пришло время создать простую форму для добавления новых постов прямо из приложения. Давайте сделаем это.
Начнем с проектирования пользовательского интерфейса:
- На главной странице добавим ссылку “Написать новый пост”.
- Эта ссылка отобразит форму с заголовком и текстовой областью для содержимого поста.
- Когда мы нажмем кнопку Сохранить, пост сохранится в базе данных.
Позже мы также добавим вход в систему и разрешим добавление постов только вошедшим пользователям. Но это позже. Какой код нам нужно написать сейчас, чтобы все заработало?
- Создадим новый презентер с формой для добавления постов.
- Определим обратный вызов (callback), который запустится после успешной отправки формы и который сохранит новый пост в базе данных.
- Создадим новый шаблон, на котором будет эта форма.
- Добавим ссылку на форму в шаблон главной страницы.
Новый презентер
Новый презентер назовем EditPresenter
и сохраним в
app/Presentation/Edit/
. Ему также необходимо подключиться к базе данных,
поэтому здесь снова напишем конструктор, который будет требовать
подключение к базе данных:
<?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);
}
Краткое резюме: этот метод получает данные из формы в виде массива
$data
, вставляет их в базу данных, создает сообщение для
пользователя об успешном сохранении поста и перенаправляет на
страницу с новым постом, чтобы мы сразу увидели, как он выглядит.
Страница для создания нового поста
Теперь создадим шаблон Edit/create.latte
:
{block content}
<h1>Новый пост</h1>
{control postForm}
Все уже должно быть понятно. Последняя строка отрисовывает форму, которую мы только что создали.
Мы могли бы создать также соответствующий метод renderCreate()
, но
это не обязательно. Нам не нужно получать какие-либо данные из базы
данных и передавать их в шаблон, так что этот метод был бы пустым. В
таких случаях метод может вообще не существовать.
Ссылка на создание постов
Вероятно, вы уже знаете, как добавить ссылку на EditPresenter
и его
действие create
. Попробуйте это сделать.
Достаточно в файл app/Presentation/Home/default.latte
добавить:
<a n:href="Edit:create">Написать новый пост</a>
Редактирование постов
Теперь добавим также возможность редактирования поста. Это будет
очень просто. У нас уже есть готовая форма postForm
, и мы можем
использовать ее и для редактирования.
Добавим новую страницу edit
в презентер EditPresenter
:
public function renderEdit(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Post not found');
}
$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
, это означает, что мы будем
редактировать пост. В этом случае мы получаем пост из базы данных и
обновляем его новыми данными $data
. Если параметр id
недоступен, то это означает, что должен быть добавлен новый пост,
поэтому мы вставляем данные $data
.
Но откуда возьмется этот параметр id
? Это параметр, который был
передан в метод renderEdit()
.
Теперь мы можем добавить ссылку в шаблон app/Presentation/Post/show.latte
:
<a n:href="Edit:edit $post->id">Редактировать пост</a>
Резюме
Блог теперь функционален, посетители активно его комментируют, и нам больше не нужен Adminer для публикации. Приложение полностью независимо, и кто угодно может добавить новый пост. Так, стоп, это, наверное, не совсем правильно, что кто угодно – и я имею в виду действительно кого угодно с доступом в интернет – может добавлять новые посты. Требуется какая-то защита, чтобы новый пост мог добавить только вошедший пользователь. Это мы рассмотрим в следующей главе.