Vytváření a editování příspěvků

To je paráda! Máme super cool nový blog, lidé urputně diskutují v komentářích a my máme konečně trochu času na další programování. Přestože je Adminer skvělý nástroj, není úplně ideální pro psaní nových příspěvků na blog. Zřejmě je ten správný čas pro vytvoření jednoduchého formuláře pro přidání nových příspěvků přímo z aplikace. Pojďme na to.

Začněme s navržením uživatelského rozhraní:

  1. Na úvodní stránce přidáme odkaz „Napsat nový příspěvek“.
  2. Tento odkaz zobrazí formulář s titulkem a textareou pro obsah příspěvku.
  3. Když klikneme na tlačítko Uložit, příspěvek se uloží do databáze.

Později také přidáme přihlašování a přidávání příspěvků umožníme pouze přihlášeným uživatelům. Ale to až později. Jaký kód potřebujeme napsat teď, aby vše fungovalo?

  1. Přidáme odkaz do šablony hlavní stránky (app/presenters/templates/Homepage/default.latte)
  2. Vytvoříme novou stránku (šablonu) na které bude onen formulář
  3. Definujeme formulář pro přidávání nových příspěvků
  4. Definujeme callback, který se spustí po úspěšném odeslání formuláře a který nový příspěvek uloží do databáze

Odkaz na nový příspěvek

Pravděpodobně již víte jak přidat odkaz na úvodní stránku. Vyzkoušejte si to.

Pokud si nejste jisti jak na to, umístíme tento kód do souboru app/presenters/templates/Homepage/default.latte:

<a n:href="Post:create">Napsat nový příspěvek</a>

Stránka pro vytvoření nového příspěvku

Právě vytvořený odkaz odkazuje na PostPresenter a jeho akci create. Můžeme přidat novou metodu renderCreate, ale ono to asi nebude nutné. Nepotřebujeme získávat žádná data z databáze a předávat je do šablony, takže by tato metoda byla prázdná. V takovýchto případech nemusí metoda vůbec existovat.

Pokud chcete, můžete zde tuto prázdnou metodu vytvořit. Možná se bude hodit později. Je to na vás.

Vytvořme nyní šablonu (app/presenters/templates/Post/create.latte):

{block content}
<h1>Nový příspěvek</h1>

{control postForm}

Vše by již mělo být jasné. Poslední řádka vykresluje formulář, který teprve vytvoříme.

Formulář pro ukládání příspěvků

Formuláře a komponenty jsme si již vysvětlili při vytváření komentářů. Pokud to stále není jasné, jděte si projít tvorbu formulářů a komponent, my zde zatím počkáme ;)

Nyní přidejme tuto metodu do presenteru PostPresenter:

protected function createComponentPostForm(): Form
{
    $form = new Form;
    $form->addText('title', 'Titulek:')
        ->setRequired();
    $form->addTextArea('content', 'Obsah:')
        ->setRequired();

    $form->addSubmit('send', 'Uložit a publikovat');
    $form->onSuccess[] = [$this, 'postFormSucceeded'];

    return $form;
}

Ukládání nového příspěvku z formuláře

Pokračujeme přidáním metody, která zpracuje data z formuláře:

public function postFormSucceeded(Form $form, \stdClass $values): void
{
    $post = $this->database->table('posts')->insert($values);

    $this->flashMessage("Příspěvek byl úspěšně publikován.", 'success');
    $this->redirect('show', $post->id);
}

Pouze rychlá rekapitulace: tato metoda získá data z formuláře, vloží je do databáze, vytvoří zprávu pro uživatele o úspěšném uložení příspěvku a přesměruje na stránku s novým příspěvkem, takže hned uvidíme, jak vypadá.

Úprava příspěvků

Nyní přidáme také možnost editace příspěvku. Bude to velmi jednoduché. Již máme hotový formulář postForm a můžeme jej použít i pro editaci. Přidáme novou stránku edit a upravíme callback, který bude schopen jednak přidat nový článek (tak jako to dělá teď) a druhak již existující článek editovat.

Přidáme metodu do presenteru PostPresenter:

public function actionEdit(int $postId): void
{
    $post = $this->database->table('posts')->get($postId);
    if (!$post) {
        $this->error('Příspěvek nebyl nalezen');
    }
    $this['postForm']->setDefaults($post->toArray());
}

Povšimněme si, že se metoda jmenuje actionEdit (a ne renderEdit, jak možná někteří čekali). Render metody se používají pro vložení dat do šablon. Oproti tomu action metody toho mohou dělat mnohem více, měly by kontrolovat, jestli požadovaná stránka může být zobrazena současným návštěvníkem, nebo uživatelem a mohou také vykonávat spoustu práce, která nenáleží callbackům. Předávání dat do šablon bude samozřejmě fungovat i v action metodách, ale není doporučeno to dělat, kvůli oddělení zodpovědností. Navíc je kód daleko lépe čitelný, pokud jej rozdělíte na renderovací metody a metody vykonávající nějakou akci.

Nyní vytvoříme další šablonu (app/presenters/templates/Post/edit.latte):

{block content}
<h1>Upravit příspěvek</h1>

{control postForm}

Rozšíříme také callback metodu:

public function postFormSucceeded(Form $form, \stdClass $values): void
{
    $postId = $this->getParameter('postId');

    if ($postId) {
        $post = $this->database->table('posts')->get($postId);
        $post->update($values);
    } else {
        $post = $this->database->table('posts')->insert($values);
    }

    $this->flashMessage('Příspěvek byl úspěšně publikován.', 'success');
    $this->redirect('show', $post->id);
}

Pokud je k dispozici parametr postId, znamená to, že budeme upravovat příspěvek. V tom případě ověříme, že požadovaný příspěvek opravdu existuje a pokud ano, aktualizujeme ho v databázi. Pokud parametr postId není k dispozici, pak to znamená, že by měl být nový příspěvek přidán.

Kde se však onen parametr postId vezme? Jedná se o parametr, který byl vložen do metody actionEdit. Nyní můžeme přidat odkaz do šablony app/presenters/templates/Post/show.latte:

<a n:href="edit $post->id">Upravit příspěvek</a>

Shrnutí

Blog je nyní funkční, návštěvníci jej aktivně komentují a my již nepotřebujeme na publikaci Adminer. Aplikace je plně nezávislá a kdokoliv může přidat nový příspěvek. Tak moment, to asi není úplně v pořádku, že kdokoliv – a tím myslím opravdu kdokoliv s přístupem na internet – může přidávat nové příspěvky. Je zapotřebí nějaké zabezpečení, aby mohl nový příspěvek přidat pouze přihlášený uživatel. Na to se podíváme v příští kapitole.