Egyetlen poszt oldal

Adjunk hozzá egy másik oldalt a blogunkhoz, amely egy adott blogbejegyzés tartalmát jeleníti meg.

Létre kell hoznunk egy új renderelési metódust, amely egy adott blogbejegyzést fog lekérni és átadni a sablonhoz. Ha ez a nézet a HomePresenter oldalon van, az nem szép, mert egy blogbejegyzésről van szó, nem pedig a kezdőlapról. Tehát hozzunk létre egy új osztályt PostPresenter és helyezzük el a app/UI/Post/. Szüksége lesz egy adatbázis-kapcsolatra, ezért a adatbázis injekció kódot ismét oda tesszük.

A PostPresenter így kell kinéznie:

<?php
namespace App\UI\Post;

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

final class PostPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

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

Be kell állítanunk egy megfelelő névteret App\UI\Post a prezenterünk számára. Ez a prezenter leképezésétől függ.

A renderShow módszer egy argumentumot igényel – a megjelenítendő poszt azonosítóját. Ezután betölti a bejegyzést az adatbázisból, és az eredményt átadja a sablonhoz.

A Home/default.latte sablonban a Post:show műveletre mutató linket adunk hozzá:

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

A {link} címke URL-címet generál, amely a Post:show akcióra mutat. Ez a tag a bejegyzés azonosítóját is továbbítja argumentumként.

Ugyanezt röviden megírhatjuk az n:attribútum használatával:

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

A n:href attribútum hasonló a {link} címkéhez.

A Post:show művelet sablonja még nem létezik. Meg tudjuk nyitni a linket erre a bejegyzésre. Tracy hibát fog mutatni, hogy miért nem létezik a Post/show.latte. Ha bármilyen más hibajelentést lát, akkor valószínűleg be kell kapcsolnia a mod_rewrite-et a webszerverén.

Tehát létrehozzuk a Post/show.latte címet ezzel a tartalommal:

{block content}

<p><a n:href="Home:default">← back to posts list</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>

Nézzük meg az egyes részeket.

Az első sor a korábban már látott “tartalom” nevű nevesített blokk definícióját kezdi. Ez egy layout sablonban fog megjelenni. Mint látható, hiányzik a {/block} végcímke. Ez opcionális.

A második sorban a blogbejegyzések listájára mutató visszahivatkozást adunk meg, így a felhasználó zökkenőmentesen tud előre-hátra navigálni a blogunkon. Ismét a n:href attribútumot használjuk, ezért a Nette gondoskodik az URL generálásáról helyettünk. A link a Home bemutató default műveletére mutat (írhatnánk n:href="Home:" is, mivel a default művelet elhagyható).

A harmadik sorban a publikációs időbélyeget formázzuk meg egy szűrővel, ahogy azt már tudjuk.

A negyedik sor a blogbejegyzés címét jeleníti meg, mint egy <h1> címként. Van egy rész, amit talán nem ismersz, ez pedig a n:block="title". Ki tudja találni, hogy mit csinál? Ha figyelmesen olvastad az előző részeket, akkor említettük a n: attributes címet. Ez egy másik példa. Ez a következővel egyenértékű:

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

Egyszerűen fogalmazva, újra definiál egy title nevű blokkot. A blokk a layout template-ben (/app/UI/@layout.latte:11) van definiálva, és az OOP felülbíráláshoz hasonlóan itt is felülírásra kerül. Ezért az oldal <title> a megjelenített bejegyzés címét fogja tartalmazni. Az oldal címét felülbíráltuk, és ehhez csak a n:block="title" kellett. Nagyszerű, nem?

A sablon ötödik és egyben utolsó sorában megjelenik a bejegyzés teljes tartalma.

A bejegyzés azonosítójának ellenőrzése

Mi történik, ha valaki megváltoztatja az URL-t és beilleszti a id címet, ami nem létezik? Egy szép “az oldal nem található” hibaüzenetet kell adnunk a felhasználónak. Frissítsük a renderelési metódust a PostPresenter:

public function renderShow(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);
	if (!$post) {
		$this->error('Post not found');
	}

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

Ha a poszt nem található, a $this->error(...) meghívása egy 404-es oldalt fog megjeleníteni egy szép és érthető üzenettel. Vegyük figyelembe, hogy a fejlesztői környezetben (a laptopon) nem fogjuk látni a hibaoldalt. Ehelyett a Tracy a kivételt fogja megmutatni a teljes részletességgel, ami elég kényelmes a fejlesztéshez. Mindkét módot ellenőrizheted, csak változtasd meg a setDebugMode címre átadott értéket a Bootstrap.php.

Összefoglaló

Van egy adatbázisunk blogbejegyzésekkel és egy webes alkalmazásunk két nézettel – az első az összes legutóbbi bejegyzés összefoglalóját, a második pedig egy adott bejegyzést jelenít meg.