Створення та редагування постів

Який чудовий час. У нас з'явився новий суперкрутий блог, люди сперечаються в коментарях, і у нас нарешті з'явився час для програмування. Хоча нам подобається Adminer, писати в ньому статті для блогу не дуже зручно. Можливо, зараз саме час додати просту форму для додавання нових постів прямо з нашого додатка. Давайте зробимо це.

Почнемо з розробки користувацького інтерфейсу:

1. На головній сторінці додамо посилання “Написати новий пост”.

  1. Воно відобразить форму із заголовком і текстовою областю для вмісту.

3. Коли ви натиснете кнопку “Зберегти”, вона збереже запис у блозі.

Пізніше ми також додамо аутентифікацію і дозволимо додавати нові повідомлення тільки користувачам, які увійшли в систему. Який код нам потрібно написати, щоб він працював?

1. Створіть новий презентер із формою для додавання постів.

  1. Визначте зворотний виклик, який буде спрацьовувати після успішного відправлення форми і який збереже нове повідомлення в базі даних.

3. Створіть новий шаблон для форми. 4. Додайте посилання на форму в шаблон головної сторінки.

Новий презентер

Назвіть новий презентер EditPresenter і збережіть його в app/UI/Edit/. Йому також необхідно під'єднатися до бази даних, тому тут ми знову пишемо конструктор, який потребуватиме під'єднання до бази даних:

<?php
namespace App\UI\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);
}

Невелике пояснення: цей метод витягує значення з форми, вставляє їх у базу даних, створює повідомлення для користувача про успішну публікацію посту і перенаправляє на сторінку, де цей пост опубліковано, щоб ви могли побачити, який він має вигляд.

Сторінка для створення нового поста

Давайте просто створимо шаблон (app/UI/Edit/create.latte):

{block content}
<h1>Новый пост</h1>

{control postForm}

Тепер усе має бути зрозуміло. Останній рядок показує форму, яку ми збираємося створити.

Ми могли б також створити відповідний метод renderCreate, але це не обов'язково. Нам не потрібно отримувати дані з бази даних і передавати їх у шаблон, тому цей метод буде порожнім. У таких випадках метод може взагалі не існувати.

Ви, ймовірно, вже знаєте, як додати посилання на EditPresenter та його дію create. Спробуйте.

Просто додайте у файл app/UI/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('Пост не найден');
	}

	$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/UI/Post/show.latte:

<a n:href="Edit:edit $post->id">Изменить пост</a>

Підіб'ємо підсумок

Блог працює, люди швидко коментують, і ми більше не покладаємося на Адміна для додавання нових постів. Блог повністю незалежний, і навіть звичайні люди можуть розміщувати там свої повідомлення. Але зачекайте, це, напевно, не нормально, що будь-хто, я маю на увазі справді будь-яка людина в Інтернеті, може написати в нашому блозі. Потрібна певна форма автентифікації, щоб тільки ті користувачі, які увійшли в систему, могли розміщувати повідомлення. Ми додамо це в наступному розділі.