Seite mit einem Beitrag
Nun erstellen wir eine weitere Seite des Blogs, die einen bestimmten Beitrag anzeigt.
Wir müssen eine neue Render-Methode erstellen, die einen bestimmten Artikel abruft und an das Template übergibt. Diese
Methode in HomePresenter
zu haben, ist nicht sehr schön, da wir über einen Artikel sprechen und nicht über die
Startseite. Erstellen wir also PostPresenter
in app/Presentation/Post/
. Dieser Presenter muss sich
ebenfalls mit der Datenbank verbinden, daher schreiben wir hier wieder einen Konstruktor, der eine Datenbankverbindung
erfordert.
PostPresenter
könnte also so aussehen:
<?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);
}
}
Wir dürfen nicht vergessen, den korrekten Namespace App\Presentation\Post
anzugeben, der der Einstellung des Presenter-Mappings unterliegt.
Die Methode renderShow
benötigt ein Argument – die ID eines bestimmten Artikels, der angezeigt werden soll.
Dann lädt sie diesen Artikel aus der Datenbank und übergibt ihn an das Template.
In das Template Home/default.latte
fügen wir einen Link zur Aktion Post:show
ein.
...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...
Das Tag {link}
generiert eine URL-Adresse, die auf die Aktion Post:show
verweist. Es übergibt auch
die ID des Beitrags als Argument.
Dasselbe können wir kürzer mit einem n:Attribut schreiben:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
Das Attribut n:href
ist analog zum Tag {link}
.
Für die Aktion Post:show
existiert jedoch noch kein Template. Wir können versuchen, den Link zu diesem Beitrag
zu öffnen. Tracy zeigt einen Fehler an, da das Template Post/show.latte
noch nicht existiert. Wenn Sie eine andere Fehlermeldung sehen, müssen Sie wahrscheinlich mod_rewrite
auf dem
Webserver aktivieren.
Erstellen wir also das Template Post/show.latte
mit diesem Inhalt:
{block content}
<p><a n:href="Home:default">← zurück zur Beitragsliste</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>
Gehen wir nun die einzelnen Teile des Templates durch.
Die erste Zeile beginnt mit der Definition eines Blocks namens “content”, genauso wie auf der Startseite. Dieser Block wird
wieder im Haupt-Template angezeigt. Wie Sie sehen, fehlt das schließende Tag {/block}
. Das ist nämlich
optional.
Auf der nächsten Zeile befindet sich ein Link zurück zur Blog-Beitragsliste, sodass sich der Benutzer einfach zwischen der
Beitragsliste und einem einzelnen Beitrag bewegen kann. Da wir das Attribut n:href
verwenden, kümmert sich Nette
selbst um die Generierung von Links. Der Link verweist auf die Aktion default
des Presenters Home
(wir
können auch n:href="Home:"
schreiben, da die Aktion mit dem Namen default
weggelassen werden kann, sie
wird automatisch ergänzt).
Die dritte Zeile formatiert die Datumsausgabe mit einem Filter, den wir bereits kennen.
Die vierte Zeile zeigt den Titel des Blogs im HTML-Tag <h1>
an. Dieses Tag enthält ein Attribut, das
Sie vielleicht nicht kennen (n:block="title"
). Raten Sie mal, was es tut? Wenn Sie den vorherigen Teil aufmerksam
gelesen haben, wissen Sie bereits, dass es sich um ein n:Attribut
handelt. Dies ist ein weiteres Beispiel dafür, das
äquivalent ist zu:
{block title}<h1>{$post->title}</h1>{/block}
Einfach gesagt, dieser Block definiert den Block namens title
neu. Dieser Block ist bereits im
Haupt-Layout-Template (/app/Presentation/@layout.latte:11
) definiert, und wie bei der Überlagerung von
Methoden in OOP wird dieser Block im Haupt-Template vollständig überlagert. Somit enthält der <title>
der
Seite nun den Titel des angezeigten Beitrags, und dafür mussten wir nur ein einfaches Attribut n:block="title"
verwenden. Großartig, nicht wahr?
Die fünfte und letzte Zeile des Templates zeigt den gesamten Inhalt eines bestimmten Beitrags an.
Überprüfung der Beitrags-ID
Was passiert, wenn jemand die ID in der URL ändert und eine nicht existierende id
einfügt? Wir sollten dem
Benutzer einen netten Fehler vom Typ “Seite nicht gefunden” anbieten. Ändern wir also die Render-Methode im
PostPresenter
ein wenig:
public function renderShow(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Seite nicht gefunden');
}
$this->template->post = $post;
}
Wenn der Beitrag nicht gefunden werden kann, zeigen wir durch den Aufruf von $this->error(...)
eine Fehlerseite
404 mit einer verständlichen Meldung an. Beachten Sie, dass Sie diese Fehlerseite im Entwicklermodus (localhost) nicht sehen
werden. Stattdessen wird Tracy mit Details zur Ausnahme angezeigt, was für die Entwicklung ziemlich vorteilhaft ist. Wenn wir uns
beide Modi anzeigen lassen möchten, ändern wir einfach das Argument der Methode setDebugMode
in der Datei
Bootstrap.php
.
Zusammenfassung
Wir haben eine Datenbank mit Beiträgen und eine Webanwendung, die zwei Ansichten hat – die erste zeigt eine Übersicht aller Beiträge und die zweite zeigt einen bestimmten Beitrag an.