Pagina cu postarea
Acum vom crea o altă pagină a blogului, care va afișa o postare specifică.
Trebuie să creăm o nouă metodă render, care va obține un articol specific și îl va transmite șablonului. A avea
această metodă în HomePresenter
nu este foarte elegant, deoarece vorbim despre un articol și nu despre pagina de
pornire. Să creăm deci PostPresenter
în app/Presentation/Post/
. Acest presenter trebuie, de asemenea,
să se conecteze la baza de date, așa că vom scrie din nou aici un constructor care va necesita conexiunea la baza de date.
PostPresenter
ar putea arăta deci astfel:
<?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);
}
}
Nu trebuie să uităm să specificăm spațiul de nume corect App\Presentation\Post
, care este supus setărilor de
maparea presenterilor.
Metoda renderShow
necesită un argument – ID-ul unui articol specific care trebuie afișat. Apoi încarcă
acest articol din baza de date și îl transmite șablonului.
În șablonul Home/default.latte
inserăm un link către acțiunea Post:show
.
...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...
Tag-ul {link}
generează adresa URL care indică spre acțiunea Post:show
. De asemenea, transmite
ID-ul postării ca argument.
Același lucru îl putem scrie prescurtat folosind n:atributul:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
Atributul n:href
este echivalentul tag-ului {link}
.
Pentru acțiunea Post:show
însă, nu există încă un șablon. Putem încerca să deschidem linkul către
această postare. Tracy va afișa o eroare, deoarece șablonul
Post/show.latte
nu există încă. Dacă vedeți un alt mesaj de eroare, probabil va trebui să activați
mod_rewrite
pe serverul web.
Creăm deci șablonul Post/show.latte
cu acest conținut:
{block content}
<p><a n:href="Home:default">← înapoi la lista postărilor</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>
Acum vom parcurge părțile individuale ale șablonului.
Prima linie începe definiția blocului cu numele “content”, la fel cum a fost pe pagina de pornire. Acest bloc va fi din
nou afișat în șablonul principal. După cum vedeți, lipsește tag-ul de închidere {/block}
. Acesta este, de
fapt, opțional.
Pe linia următoare este un link înapoi la lista articolelor blogului, astfel încât utilizatorul să poată naviga ușor
între lista articolelor și unul specific. Deoarece folosim atributul n:href
, Nette se ocupă singur de generarea
linkurilor. Linkul indică spre acțiunea default
a presenterului Home
(putem scrie și
n:href="Home:"
, deoarece acțiunea cu numele default
poate fi omisă, se completează automat).
A treia linie formatează afișarea datei folosind filtrul pe care îl cunoaștem deja.
A patra linie afișează titlul blogului în tag-ul HTML <h1>
. Acest tag conține un atribut pe care
poate nu îl cunoașteți (n:block="title"
). Ghiciți ce face? Dacă ați citit partea anterioară cu atenție,
știți deja că este vorba despre un n:atribut
. Acesta este un alt exemplu al lor, care este echivalent cu:
{block title}<h1>{$post->title}</h1>{/block}
Simplu spus, acest bloc redefinește blocul cu numele title
. Acest bloc este deja definit în șablonul
layout principal (/app/Presentation/@layout.latte:11
) și, la fel ca la suprascrierea metodelor în OOP, la
fel acest bloc din șablonul principal va fi suprascris. Deci <title>
paginii conține acum titlul postării
afișate și ne-a fost suficient să folosim doar un singur atribut simplu n:block="title"
. Minunat, nu-i așa?
A cincea și ultima linie a șablonului afișează întregul conținut al unei postări specifice.
Verificarea ID-ului postării
Ce se întâmplă dacă cineva modifică ID-ul în URL și introduce un id
inexistent? Ar trebui să oferim
utilizatorului o eroare frumoasă de tipul “pagina nu a fost găsită”. Modificăm deci puțin metoda render în
PostPresenter
:
public function renderShow(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Pagina nu a fost găsită');
}
$this->template->post = $post;
}
Dacă postarea nu poate fi găsită, apelând $this->error(...)
afișăm pagina de eroare 404 cu un mesaj
inteligibil. Atenție, în modul dezvoltator (localhost) nu veți vedea această pagină de eroare. În schimb, se va afișa Tracy
cu detalii despre excepție, ceea ce este destul de avantajos pentru dezvoltare. Dacă dorim să ne afișăm ambele moduri, este
suficient să schimbăm argumentul metodei setDebugMode
în fișierul Bootstrap.php
.
Rezumat
Avem o bază de date cu postări și o aplicație web care are două vizualizări – prima afișează o prezentare generală a tuturor postărilor și a doua afișează o postare specifică.