Stránka s příspěvkem

Nyní si vytvoříme další stránku blogu, která bude zobrazovat jeden konkrétní příspěvek.

Musíme si vytvořit novou render metodu, která získá jeden konkrétní článek a předá jej do šablony. Mít tuto metodu v HomepagePresenter není moc hezké, protože se bavíme o článku a ne úvodní stránce. Vytvořme si tedy PostPresenter v app/presenters/PostPresenter.php. Tento presenter se také potřebuje připojit k databázi, takže zde opět napíšeme konstruktor, který bude vyžadovat databázové připojení.

PostPresenter by mohl tedy vypadat takto:

namespace App\Presenters;

use Nette;
use Nette\Application\UI\Form;


class PostPresenter extends Nette\Application\UI\Presenter
{
    /** @var Nette\Database\Context */
    private $database;

    public function __construct(Nette\Database\Context $database)
    {
        $this->database = $database;
    }

    public function renderShow(int $postId): void
    {
        $this->template->post = $this->database->table('posts')->get($postId);
    }
}

Nesmíme zapomenou uvést správný namespace App\Presenters, který podléhá nastavení mapování presenterů.

Metoda renderShow vyžaduje jeden argument – ID jednoho konkrétního článku, který má být zobrazen. Poté tento článek načte z databáze a předá ho do šablony.

Do šablony app/presenters/templates/Homepage/default.latte vložíme odkaz na akci Post:show.

...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...

Makro {link} generuje URL adresu, která směřuje na akci Post:show. Toto makro také předává ID příspěvku jako argument.

Totéž můžeme zapsat zkráceně pomocí n:makra:

...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...

Atribut n:href je aliasem pro makro {link}.

Pro akci Post:show však ještě neexistuje šablona. Můžeme si vyzkoušet otevřít odkaz na tento příspěvek. Tracy zobrazí error, protože šablona app/presenters/templates/Post/show.latte ještě neexistuje. Pokud vidíte jiné chybové hlášení, tak pravděpodobně budete muset zapnout mod_rewrite ve webserveru.

Vytvoříme tedy šablonu app/presenters/templates/Post/show.latte s tímto obsahem:

{block content}

<p><a n:href="Homepage:default">← zpět na výpis příspěvků</a></p>

<div class="date">{$post->created_at|date:'F j, Y'}</div>

<h1 n:block="title">{$post->title}</h1>

<div class="post">{$post->content}</div>

Nyní si projdeme jednotlivé části šablony.

První řádka začíná definici bloku s názvem „content“ stejně jako tomu bylo na úvodní stránce. Tento blok bude opět zobrazen v hlavní šabloně.

Na další řádce je odkaz zpět na výpis článků blogu, takže se uživatel může jednoduše pohybovat mezi výpisem článků a jedním konkrétním. Protože používáme makro n:href, tak se Nette samo postará o generování odkazů. Odkaz směřuje na akci default presenteru Homepage (můžeme napsat také n:href="Homepage:", protože akce s názvem default může být vynechána, doplní se automaticky).

Třetí řádka formátuje výpis datumu pomocí filtru, který už známe.

Čtvrtá řádka zobrazuje titulek blogu v HTML tagu <h1>. Tento tag obsahuje atribut, který možná neznáte (n:block="title"). Uhodnete, co dělá? Pokud jste četli předchozí část pozorně, tak již víte, že se jedná o n:makro. Toto je jejich další příklad, který je ekvivalentní k:

{block title}<h1>{$post->title}</h1>{/block}

Jednoduše řečeno, tento blok předefinovává blok s názvem title. Tento blok je již definován v hlavní layout šabloně (/app/presenters/templates/@layout.latte:11) a tak jako u překrývání metod v OOP, úplně stejně se tento blok v hlavní šabloně překryje. Takže <title> stránky nyní obsahuje titulek zobrazeného příspěvku a stačilo nám k tomu použít pouze jedno jednoduchého makra n:block="title". Skvělé, že?

Pátá a poslední řádka šablony zobrazuje celý obsah jednoho konkrétního příspěvku.

Kontrola ID příspěvku

Co se stane, když někdo změní ID v URL a vloží nějaké neexistující postId? Měli bychom uživateli nabídnout pěknou chybu typu „stránka nebyla nalezena“. Pozměníme tedy trošku render metodu v souboru app/presenters/PostPresenter.php:

public function renderShow(int $postId): void
{
    $post = $this->database->table('posts')->get($postId);
    if (!$post) {
        $this->error('Stránka nebyla nalezena');
    }

    $this->template->post = $post;
}

Pokud nemůže být příspěvek nalezen, zavoláním $this->error(...) zobrazíme chybovou stránku 404 se srozumitelnou hláškou. Pozor na to, že v debug módu (localhost) tuto chybovou stránku neuvidíte. Místo toho se ukáže Tracy s detaily o výjimce, což je docela výhodné pro vývoj. Můžeme si nechat zobrazit oba módy, stačí pouze změnit argument metody setDebugMode v souboru bootstrap.php.

Shrnutí

Máme databázi s příspěvky a webovou aplikaci, která má dva pohledy – první zobrazuje přehled všech příspěvků a druhá zobrazuje jeden konkrétní příspěvek.