Stran s prispevkom

Zdaj si bomo ustvarili še eno stran bloga, ki bo prikazovala en konkreten prispevek.

Ustvariti moramo novo render metodo, ki bo pridobila en konkreten članek in ga predala predlogi. Imeti to metodo v HomePresenter ni zelo lepo, saj govorimo o članku in ne o uvodni strani. Ustvarimo si torej PostPresenter v app/Presentation/Post/. Ta presenter se prav tako mora povezati s podatkovno bazo, zato bomo tukaj spet napisali konstruktor, ki bo zahteval podatkovno povezavo.

PostPresenter bi torej lahko izgledal takole:

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

Ne smemo pozabiti navesti pravilnega imenskega prostora App\Presentation\Post, ki sledi nastavitvam mapiranja presenterjev.

Metoda renderShow zahteva en argument – ID enega konkretnega članka, ki naj bo prikazan. Nato ta članek naloži iz podatkovne baze in ga preda predlogi.

V predlogo Home/default.latte vstavimo povezavo na akcijo Post:show.

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

Oznaka {link} generira URL naslov, ki kaže na akcijo Post:show. Prav tako preda ID prispevka kot argument.

Enako lahko zapišemo skrajšano s pomočjo n:atributa:

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

Atribut n:href je analogija oznake {link}.

Za akcijo Post:show pa še ne obstaja predloga. Lahko si poskusimo odpreti povezavo na ta prispevek. Tracy bo prikazala napako, ker predloga Post/show.latte še ne obstaja. Če vidite drugačno sporočilo o napaki, boste verjetno morali vklopiti mod_rewrite na spletnem strežniku.

Ustvarimo torej predlogo Post/show.latte s to vsebino:

{block content}

<p><a n:href="Home:default">← nazaj na izpis prispevkov</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>

Zdaj si oglejmo posamezne dele predloge.

Prva vrstica začenja definicijo bloka z imenom “content” enako kot je bilo na uvodni strani. Ta blok bo ponovno prikazan v glavni predlogi. Kot vidite, manjka končna oznaka {/block}. Ta je namreč neobvezna.

Na naslednji vrstici je povezava nazaj na izpis člankov bloga, tako da se uporabnik lahko enostavno premika med izpisom člankov in enim konkretnim. Ker uporabljamo atribut n:href, bo Nette sam poskrbel za generiranje povezav. Povezava kaže na akcijo default presenterja Home (lahko napišemo tudi n:href="Home:", ker lahko akcijo z imenom default izpustimo, dopolni se samodejno).

Tretja vrstica formatira izpis datuma s pomočjo filtra, ki ga že poznamo.

Četrta vrstica prikazuje naslov bloga v HTML oznaki <h1>. Ta oznaka vsebuje atribut, ki ga morda ne poznate (n:block="title"). Uganete, kaj dela? Če ste prejšnji del pozorno prebrali, že veste, da gre za n:atribut. To je njihov nadaljnji primer, ki je ekvivalenten:

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

Preprosto rečeno, ta blok predifinira blok z imenom title. Ta blok je že definiran v glavni layout predlogi (/app/Presentation/@layout.latte:11) in tako kot pri prekrivanju metod v OOP, se popolnoma enako ta blok v glavni predlogi prekrije. Torej <title> strani zdaj vsebuje naslov prikazanega prispevka in za to smo potrebovali uporabiti samo enega preprostega atributa n:block="title". Super, kajne?

Peta in zadnja vrstica predloge prikazuje celotno vsebino enega konkretnega prispevka.

Preverjanje ID prispevka

Kaj se zgodi, če nekdo spremeni ID v URL-ju in vstavi nek neobstoječ id? Uporabniku bi morali ponuditi lepo napako tipa “stran ni bila najdena”. Malo spremenimo torej render metodo v PostPresenter:

public function renderShow(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);
	if (!$post) {
		$this->error('Stran ni bila najdena');
	}

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

Če prispevka ni mogoče najti, s klicem $this->error(...) prikažemo stran z napako 404 z razumljivim sporočilom. Pozor na to, da v razvijalskem načinu (localhost) te strani z napako ne boste videli. Namesto tega se bo prikazala Tracy s podrobnostmi o izjemi, kar je precej ugodno za razvoj. Če si želimo prikazati oba načina, je dovolj samo spremeniti argument metode setDebugMode v datoteki Bootstrap.php.

Povzetek

Imamo podatkovno bazo s prispevki in spletno aplikacijo, ki ima dva pogleda – prvi prikazuje pregled vseh prispevkov in drugi prikazuje en konkreten prispevek.