Pagina con il post
Ora creeremo un'altra pagina del blog che visualizzerà un singolo post specifico.
Dobbiamo creare un nuovo metodo render che ottenga un articolo specifico e lo passi al template. Avere questo metodo in
HomePresenter
non è molto bello, perché stiamo parlando di un articolo e non della pagina iniziale. Creiamo quindi
PostPresenter
in app/Presentation/Post/
. Questo presenter ha anche bisogno di connettersi al database,
quindi scriveremo di nuovo un costruttore che richiederà la connessione al database.
PostPresenter
potrebbe quindi apparire così:
<?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);
}
}
Non dobbiamo dimenticare di specificare il namespace corretto App\Presentation\Post
, che è soggetto
all'impostazione del mapping dei
presenter.
Il metodo renderShow
richiede un argomento – l'ID di un articolo specifico che deve essere visualizzato.
Successivamente carica questo articolo dal database e lo passa al template.
Nel template Home/default.latte
inseriamo 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
. Passa anche l'ID del post come
argomento.
Lo stesso possiamo scriverlo in forma abbreviata usando un n:attributo:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
L'attributo n:href
è analogo al tag {link}
.
Per l'azione Post:show
, tuttavia, non esiste ancora un template. Possiamo provare ad aprire il link a questo post.
Tracy visualizzerà un errore, perché il template Post/show.latte
non
esiste ancora. Se vedete un messaggio di errore diverso, probabilmente dovrete abilitare mod_rewrite
sul
webserver.
Creiamo quindi il template Post/show.latte
con questo contenuto:
{block content}
<p><a n:href="Home:default">← torna all'elenco dei post</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>
Ora esaminiamo le singole parti del template.
La prima riga inizia la definizione del blocco con il nome “content” proprio come sulla pagina iniziale. Questo blocco
sarà nuovamente visualizzato nel template principale. Come vedete, manca il tag di chiusura {/block}
. Questo è
infatti facoltativo.
Sulla riga successiva c'è un link per tornare all'elenco degli articoli del blog, così l'utente può muoversi facilmente tra
l'elenco degli articoli e uno specifico. Poiché usiamo l'attributo n:href
, Nette si occupa da solo della generazione
dei link. Il link punta all'azione default
del presenter Home
(possiamo scrivere anche
n:href="Home:"
, perché l'azione con il nome default
può essere omessa, viene aggiunta
automaticamente).
La terza riga formatta la visualizzazione della data usando il filtro che già conosciamo.
La quarta riga visualizza il titolo del blog nel tag HTML <h1>
. Questo tag contiene un attributo che
forse non conoscete (n:block="title"
). Indovinate cosa fa? Se avete letto attentamente la parte precedente, sapete
già che si tratta di un n:attributo
. Questo è un altro esempio, che è equivalente a:
{block title}<h1>{$post->title}</h1>{/block}
In parole povere, questo blocco ridefinisce il blocco con il nome title
. Questo blocco è già definito nel
template principale layout (/app/Presentation/@layout.latte:11
) e, proprio come nella sovrascrittura dei
metodi in OOP, questo blocco nel template principale viene sovrascritto allo stesso modo. Quindi il <title>
della pagina ora contiene il titolo del post visualizzato e ci è bastato usare solo un semplice attributo
n:block="title"
. Fantastico, vero?
La quinta e ultima riga del template visualizza l'intero contenuto di un post specifico.
Controllo dell'ID del post
Cosa succede se qualcuno cambia l'ID nell'URL e inserisce un id
inesistente? Dovremmo offrire all'utente un
bell'errore del tipo “pagina non trovata”. Modifichiamo quindi un po' il metodo render in PostPresenter
:
public function renderShow(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Pagina non trovata');
}
$this->template->post = $post;
}
Se il post non può essere trovato, chiamando $this->error(...)
visualizziamo una pagina di errore 404 con un
messaggio comprensibile. Attenzione al fatto che in modalità sviluppatore (localhost) non vedrete questa pagina di errore. Al suo
posto apparirà Tracy con i dettagli sull'eccezione, il che è abbastanza vantaggioso per lo sviluppo. Se vogliamo visualizzare
entrambe le modalità, basta semplicemente cambiare l'argomento del metodo setDebugMode
nel file
Bootstrap.php
.
Riepilogo
Abbiamo un database con i post e un'applicazione web che ha due viste – la prima visualizza un riepilogo di tutti i post e la seconda visualizza un post specifico.