Einzelner Beitrag Seite

Fügen wir unserem Blog eine weitere Seite hinzu, die den Inhalt eines bestimmten Blogbeitrags anzeigt.

Wir müssen eine neue Render-Methode erstellen, die einen bestimmten Blogeintrag abruft und ihn an die Vorlage weitergibt. Diese Ansicht in HomePresenter zu haben, ist nicht schön, da es sich um einen Blogeintrag und nicht um die Homepage handelt. Also erstellen wir eine neue Klasse PostPresenter und platzieren sie in app/UI/Post/. Sie benötigt eine Datenbankverbindung, also fügen wir den Datenbankinjektions-Code dort wieder ein.

Die PostPresenter sollte so aussehen:

<?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);
	}
}

Wir müssen einen korrekten Namespace App\UI\Post für unseren Präsentator festlegen. Dies hängt von der Zuordnung der Präsentatoren ab.

Die Methode renderShow benötigt ein Argument – die ID des Beitrags, der angezeigt werden soll. Dann lädt sie den Beitrag aus der Datenbank und übergibt das Ergebnis an die Vorlage.

In der Vorlage Home/default.latte fügen wir einen Link zur Aktion Post:show hinzu:

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

Das Tag {link} erzeugt eine URL-Adresse, die auf die Aktion Post:show verweist. Dieser Tag leitet auch die ID des Beitrags als Argument weiter.

Das Gleiche können wir kurz mit n:attribute schreiben:

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

Das Attribut n:href ist dem Tag {link} ähnlich.

Die Vorlage für die Aktion Post:show existiert noch nicht. Wir können einen Link zu diesem Beitrag öffnen. Tracy wird eine Fehlermeldung anzeigen, warum Post/show.latte nicht existiert. Wenn Sie eine andere Fehlermeldung sehen, müssen Sie wahrscheinlich mod_rewrite in Ihrem Webserver einschalten.

Wir werden also Post/show.latte mit diesem Inhalt erstellen:

{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>

Schauen wir uns die einzelnen Teile an.

Die erste Zeile beginnt mit der Definition eines benannten Blocks namens “content”, den wir bereits gesehen haben. Er wird in einer Layoutvorlage angezeigt. Wie Sie sehen können, fehlt der Endtag {/block}. Er ist optional.

Die zweite Zeile enthält einen Rückverweis auf die Liste der Blog-Einträge, so dass der Benutzer problemlos in unserem Blog hin und her navigieren kann. Wir verwenden wieder das Attribut n:href, so dass Nette die URL für uns generiert. Der Link verweist auf die Aktion default des Presenters Home (Sie könnten auch n:href="Home:" schreiben, da die Aktion default weggelassen werden kann).

In der dritten Zeile wird der Zeitstempel der Veröffentlichung mit einem Filter formatiert, wie wir bereits wissen.

Die vierte Zeile zeigt den Titel des Blogbeitrags als <h1> Überschrift. Es gibt einen Teil, mit dem Sie vielleicht nicht vertraut sind, und das ist n:block="title". Können Sie erraten, was er bewirkt? Wenn Sie die vorherigen Teile aufmerksam gelesen haben, haben wir n: attributes erwähnt. Dies ist ein weiteres Beispiel. Es ist gleichbedeutend mit:

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

In einfachen Worten: Es definiert einen Block namens title neu. Der Block ist in der Layout-Vorlage (/app/UI/@layout.latte:11) definiert und wird hier, wie bei OOP-Überschreibungen, überschrieben. Daher wird die Seite <title> den Titel des angezeigten Beitrags enthalten. Wir haben den Titel der Seite überschrieben, und alles, was wir brauchten, war n:block="title". Großartig, nicht wahr?

In der fünften und letzten Zeile der Vorlage wird der gesamte Inhalt Ihres Beitrags angezeigt.

Überprüfen der Post-ID

Was passiert, wenn jemand die URL ändert und postId einfügt, die nicht existiert? Wir sollten dem Benutzer eine schöne Fehlermeldung “Seite nicht gefunden” geben. Aktualisieren wir die Render-Methode 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;
}

Wenn der Beitrag nicht gefunden werden kann, wird durch den Aufruf von $this->error(...) eine 404-Seite mit einer schönen und verständlichen Meldung angezeigt. Beachten Sie, dass Sie in Ihrer Entwicklungsumgebung (auf Ihrem Laptop) die Fehlerseite nicht sehen werden. Stattdessen zeigt Tracy die Ausnahme mit allen Details an, was für die Entwicklung sehr praktisch ist. Sie können beide Modi prüfen, indem Sie den an setDebugMode übergebenen Wert in Bootstrap.php ändern.

Zusammenfassung

Wir haben eine Datenbank mit Blog-Beiträgen und eine Web-Applikation mit zwei Ansichten – die erste zeigt die Zusammenfassung aller aktuellen Beiträge, die zweite einen bestimmten Beitrag an.