Page de l'article

Créons maintenant une autre page du blog, qui affichera un article spécifique.

Nous devons créer une nouvelle méthode render, qui obtiendra un article spécifique et le transmettra au template. Avoir cette méthode dans HomePresenter n'est pas très propre, car nous parlons d'un article et non de la page d'accueil. Créons donc PostPresenter dans app/Presentation/Post/. Ce presenter a également besoin de se connecter à la base de données, nous écrirons donc à nouveau un constructeur qui nécessitera une connexion à la base de données.

PostPresenter pourrait donc ressembler à ceci :

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

Nous ne devons pas oublier d'indiquer le namespace correct App\Presentation\Post, qui est soumis aux paramètres de mappage des presenters.

La méthode renderShow nécessite un argument – l'ID d'un article spécifique qui doit être affiché. Ensuite, elle charge cet article depuis la base de données et le transmet au template.

Dans le template Home/default.latte, insérons un lien vers l'action Post:show.

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

La balise {link} génère une adresse URL qui pointe vers l'action Post:show. Elle transmet également l'ID de l'article comme argument.

Nous pouvons écrire la même chose de manière abrégée en utilisant un n:attribut :

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

L'attribut n:href est analogue à la balise {link}.

Cependant, il n'existe pas encore de template pour l'action Post:show. Nous pouvons essayer d'ouvrir le lien vers cet article. Tracy affichera une erreur, car le template Post/show.latte n'existe pas encore. Si vous voyez un autre message d'erreur, vous devrez probablement activer mod_rewrite sur le serveur web.

Créons donc le template Post/show.latte avec ce contenu :

{block content}

<p><a n:href="Home:default">← retour à la liste des articles</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>

Passons maintenant en revue les différentes parties du template.

La première ligne commence la définition d'un bloc nommé “content”, comme c'était le cas sur la page d'accueil. Ce bloc sera à nouveau affiché dans le template principal. Comme vous pouvez le voir, la balise de fin {/block} est manquante. Elle est en effet facultative.

Sur la ligne suivante se trouve un lien de retour vers la liste des articles du blog, afin que l'utilisateur puisse facilement naviguer entre la liste des articles et un article spécifique. Comme nous utilisons l'attribut n:href, Nette s'occupe lui-même de la génération des liens. Le lien pointe vers l'action default du presenter Home (nous pouvons également écrire n:href="Home:", car l'action nommée default peut être omise, elle est complétée automatiquement).

La troisième ligne formate l'affichage de la date à l'aide du filtre que nous connaissons déjà.

La quatrième ligne affiche le titre du blog dans la balise HTML <h1>. Cette balise contient un attribut que vous ne connaissez peut-être pas (n:block="title"). Devinez-vous ce qu'il fait ? Si vous avez lu attentivement la partie précédente, vous savez déjà qu'il s'agit d'un n:attribut. C'est un autre exemple de ceux-ci, qui est équivalent à :

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

En termes simples, ce bloc redéfinit le bloc nommé title. Ce bloc est déjà défini dans le template layout principal (/app/Presentation/@layout.latte:11) et, tout comme pour le remplacement de méthodes en POO, ce bloc dans le template principal est complètement remplacé. Ainsi, le <title> de la page contient maintenant le titre de l'article affiché, et il nous a suffi d'utiliser un simple attribut n:block="title". Génial, n'est-ce pas ?

La cinquième et dernière ligne du template affiche l'intégralité du contenu d'un article spécifique.

Vérification de l'ID de l'article

Que se passe-t-il si quelqu'un modifie l'ID dans l'URL et insère un id inexistant ? Nous devrions proposer à l'utilisateur une belle erreur de type “page non trouvée”. Modifions donc un peu la méthode render dans PostPresenter :

public function renderShow(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);
	if (!$post) {
		$this->error('Page non trouvée');
	}

	$this->template->post = $post;
}

Si l'article ne peut pas être trouvé, en appelant $this->error(...), nous affichons une page d'erreur 404 avec un message compréhensible. Attention, en mode développeur (localhost), vous ne verrez pas cette page d'erreur. À la place, Tracy s'affichera avec les détails de l'exception, ce qui est assez pratique pour le développement. Si nous voulons afficher les deux modes, il suffit de changer l'argument de la méthode setDebugMode dans le fichier Bootstrap.php.

Résumé

Nous avons une base de données avec des articles et une application web qui a deux vues – la première affiche un aperçu de tous les articles et la seconde affiche un article spécifique.