Pagina del singolo post
Aggiungiamo un'altra pagina al nostro blog, che mostrerà il contenuto di un particolare post.
Dobbiamo creare un nuovo metodo di rendering, che recupererà un post specifico del blog e lo passerà al template. Avere
questa vista in HomePresenter
non è bello, perché si tratta di un post del blog, non della homepage. Quindi,
creiamo una nuova classe PostPresenter
e posizioniamola in app/UI/Post/
. Avrà bisogno di una
connessione al database, quindi inseriamo di nuovo il codice database injection.
PostPresenter
dovrebbe avere questo aspetto:
<?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);
}
}
Dobbiamo impostare un namespace App\UI\Post
corretto per il nostro presentatore. Dipende dalla mappatura del presentatore.
Il metodo renderShow
richiede un solo parametro: l'ID del post da visualizzare. Quindi, carica il post dal
database e passa il risultato al template.
Nel modello Home/default.latte
aggiungiamo un link all'azione Post:show
:
...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...
Il tag {link}
genera un indirizzo URL che punta all'azione Post:show
. Questo tag inoltra anche l'ID
del post come argomento.
Lo stesso si può scrivere brevemente usando n:attribute:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
L'attributo n:href
è simile al tag {link}
.
Il template per l'azione Post:show
non esiste ancora. Possiamo aprire un link a questo post. Tracy mostrerà un errore, perché Post/show.latte
non esiste. Se viene
visualizzato un altro errore, probabilmente è necessario attivare il mod_rewrite nel server web.
Creeremo quindi Post/show.latte
con questo contenuto:
{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>
Diamo un'occhiata alle singole parti.
La prima riga inizia la definizione di un blocco con nome chiamato “content”, che abbiamo visto in precedenza.
Verrà visualizzato in un modello di layout. Come si può notare, manca il tag finale {/block}
. È
opzionale.
La seconda riga fornisce un backlink all'elenco dei post del blog, in modo che l'utente possa navigare agevolmente avanti e
indietro nel nostro blog. Utilizziamo di nuovo l'attributo n:href
, quindi Nette si occuperà di generare l'URL per
noi. Il link punta all'azione default
del presentatore Home
(si potrebbe anche scrivere
n:href="Home:"
, perché l'azione default
può essere omessa).
La terza riga formatta il timestamp di pubblicazione con un filtro, come già sappiamo.
La quarta riga mostra il titolo del post del blog come un <h1>
titolo. C'è una parte che forse non
conoscete: n:block="title"
. Riuscite a indovinare cosa fa? Se avete letto attentamente le parti precedenti, abbiamo
menzionato n: attributes
. Questo è un altro esempio. È equivalente a:
{block title}<h1>{$post->title}</h1>{/block}
In parole povere, ridefinisce un blocco chiamato title
. Il blocco è definito nel modello di
layout (/app/UI/@layout.latte:11
) e, come per l'overriding OOP, viene sovrascritto qui. Pertanto, la pagina
<title>
conterrà il titolo del post visualizzato. Abbiamo sovrascritto il titolo della pagina e tutto ciò di
cui avevamo bisogno era n:block="title"
. Ottimo, no?
La quinta e ultima riga del template mostra il contenuto completo del post.
Controllo dell'ID del post
Cosa succede se qualcuno altera l'URL e inserisce id
che non esiste? Dovremmo fornire all'utente un simpatico
errore di “pagina non trovata”. Aggiorniamo il metodo di rendering in 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;
}
Se il post non può essere trovato, la chiamata a $this->error(...)
mostrerà una pagina 404 con un messaggio
chiaro e comprensibile. Si noti che nell'ambiente di sviluppo (sul portatile), non si vedrà la pagina di errore. Invece, Tracy
mostrerà l'eccezione con tutti i dettagli, il che è piuttosto comodo per lo sviluppo. È possibile controllare entrambe le
modalità, basta cambiare il valore passato a setDebugMode
in Bootstrap.php
.
Riepilogo
Abbiamo un database con i post di un blog e un'applicazione web con due viste: la prima visualizza il riepilogo di tutti i post recenti e la seconda visualizza un post specifico.