Tworzenie i edycja wpisów
Świetnie! Mamy super fajnego nowego bloga, ludzie aktywnie dyskutują w komentarzach, a my w końcu mamy trochę czasu na dalsze programowanie. Choć Adminer to świetne narzędzie, nie jest zbyt wygodny do pisania nowych wpisów blogowych. Może to właściwy moment, żeby utworzyć prosty formularz do dodawania nowych wpisów bezpośrednio z aplikacji. Zróbmy to.
Zacznijmy od zaprojektowania interfejsu użytkownika:
- Na stronie głównej dodamy odnośnik “Napisz nowy wpis”.
- Odnośnik ten wyświetli formularz z polem tytułu i textareą na treść wpisu.
- Gdy klikniemy przycisk Zapisz, wpis zostanie zapisany do bazy danych.
Później dodamy też uwierzytelnianie i pozwolimy dodawać nowe wpisy tylko zalogowanym użytkownikom. Ale zróbmy to później. Jaki kod musimy teraz napisać, żeby wszystko działało?
- Utworzyć nowy presenter z formularzem do dodawania wpisów.
- Zdefiniować callback, który wywoła się po udanym wysłaniu formularza i zapisze nowy wpis do bazy danych.
- Utworzyć nowy szablon dla formularza.
- Dodać odnośnik do formularza w szablonie strony głównej.
Nowy presenter
Nazwijmy nowy presenter EditPresenter i zapiszmy go w app/Presentation/Edit/EditPresenter.php. Musi
też połączyć się z bazą danych, więc i tutaj piszemy konstruktor wymagający połączenia z bazą:
<?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,
) {
}
}
Formularz do zapisywania wpisów
Formularze i komponenty omówiliśmy już, gdy dodawaliśmy wsparcie dla komentarzy. Jeśli nadal nie jest to jasne, idź powtórzyć sobie, jak działają formularze i komponenty, my tu poczekamy ;)
Dodaj teraz do EditPresenter tę metodę:
protected function createComponentPostForm(): Form
{
$form = new Form;
$form->addText('title', 'Tytuł:')
->setRequired();
$form->addTextArea('content', 'Treść:')
->setRequired();
$form->addSubmit('send', 'Zapisz i opublikuj');
$form->onSuccess[] = $this->postFormSucceeded(...);
return $form;
}
Zapis nowego wpisu z formularza
Kontynuujmy, dodając metodę obsługującą:
private function postFormSucceeded(array $data): void
{
$post = $this->database
->table('posts')
->insert($data);
$this->flashMessage('Wpis został pomyślnie opublikowany.', 'success');
$this->redirect('Post:show', $post->id);
}
Szybkie wyjaśnienie: pobiera wartości z formularza, wstawia je do bazy danych, tworzy dla użytkownika komunikat, że wpis został pomyślnie zapisany, i przekierowuje na stronę, gdzie ten wpis jest opublikowany, żebyś mógł zobaczyć, jak wygląda.
Strona do tworzenia nowego wpisu
Utwórzmy teraz szablon Edit/create.latte:
{block content}
<h1>Nowy wpis</h1>
{control postForm}
Wszystko powinno być już jasne. Ostatnia linia renderuje formularz, który przed chwilą utworzyliśmy.
Moglibyśmy utworzyć też odpowiadającą metodę renderCreate(), ale nie jest to konieczne. Nie musimy pobierać
żadnych danych z bazy ani przekazywać ich do szablonu, więc metoda byłaby pusta. W takich przypadkach metoda w ogóle nie
musi istnieć.
Odnośnik do tworzenia wpisów
Zapewne już wiesz, jak dodać odnośnik do EditPresenter i jego akcji create. Wypróbuj to.
Wystarczy dopisać do pliku app/Presentation/Home/default.latte:
<a n:href="Edit:create">Napisz nowy wpis</a>
Edycja wpisów
Dodajmy teraz możliwość edycji istniejących wpisów. Będzie to bardzo proste. Mamy już formularz postForm
i możemy użyć go także do edycji.
Dodamy do EditPresenter nową stronę edit:
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());
}
I utworzymy odpowiadający szablon Edit/edit.latte:
{block content}
<h1>Edycja wpisu</h1>
{control postForm}
Oraz zaktualizujemy metodę postFormSucceeded, która będzie potrafić albo dodać nowy wpis (jak robi teraz),
albo edytować istniejące:
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('Wpis został pomyślnie opublikowany.', 'success');
$this->redirect('Post:show', $post->id);
}
Gdy podany jest parametr id, oznacza to, że wpis jest edytowany. W takim przypadku sprawdzimy, czy wpis
rzeczywiście istnieje, a jeśli tak, zaktualizujemy go w bazie danych. Jeśli id nie jest podane, oznacza to, że ma
zostać dodany nowy wpis.
Ale skąd bierze się id? To parametr przekazywany metodzie renderEdit.
Możesz teraz dodać odnośnik do szablonu app/Presentation/Post/show.latte:
<a n:href="Edit:edit $post->id">Edytuj ten wpis</a>
Podsumowanie
Blog działa, ludzie ochoczo komentują, a my nie polegamy już przy dodawaniu nowych wpisów na Adminerze. Jest w pełni niezależny i nawet zwykli ludzie mogą tam pisać. Ale chwila, to chyba nie jest w porządku, że każdy, i to naprawdę każdy w internecie, może pisać na naszym blogu. Potrzebna jest jakaś forma uwierzytelniania, żeby pisać mogli tylko zalogowani użytkownicy. Dodamy to w następnym rozdziale.