Commentaires
Nous avons mis en ligne le blog sur le serveur web et publié quelques articles très intéressants en utilisant Adminer. Les gens lisent notre blog et en sont très enthousiastes. Nous recevons chaque jour de nombreux e-mails de compliments. Mais à quoi servent tous ces éloges si nous ne les avons que dans nos e-mails et que personne ne peut les lire ? Il serait préférable que le lecteur puisse commenter directement l'article, afin que tout le monde puisse lire à quel point nous sommes géniaux.
Programmons donc les commentaires.
Création d'une nouvelle table
Lançons Adminer et créons une table comments
avec les colonnes suivantes :
id
int, cochez autoincrement (AI)post_id
, clé étrangère qui référence la tableposts
name
varchar, longueur 255email
varchar, longueur 255content
textcreated_at
timestamp
La table devrait donc ressembler à quelque chose comme ça :

N'oubliez pas d'utiliser à nouveau le stockage InnoDB.
CREATE TABLE `comments` (
`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`post_id` int(11) NOT NULL,
`name` varchar(250) NOT NULL,
`email` varchar(250) NOT NULL,
`content` text NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`)
) ENGINE=InnoDB CHARSET=utf8;
Formulaire de commentaire
Tout d'abord, nous devons créer un formulaire qui permettra aux utilisateurs de commenter les articles. Le Nette Framework a un support incroyable pour les formulaires. Nous pouvons les configurer dans le presenter et les afficher dans le template.
Le Nette Framework utilise le concept de composants. Un composant est une classe réutilisable, ou une partie de
code, qui peut être attachée à un autre composant. Même le presenter est un composant. Chaque composant est créé via une
factory. Créons donc une factory pour le formulaire de commentaire dans le presenter PostPresenter
.
protected function createComponentCommentForm(): Form
{
$form = new Form; // signifie Nette\Application\UI\Form
$form->addText('name', 'Nom :')
->setRequired();
$form->addEmail('email', 'E-mail :');
$form->addTextArea('content', 'Commentaire :')
->setRequired();
$form->addSubmit('send', 'Publier le commentaire');
return $form;
}
Expliquons cela un peu plus. La première ligne crée une nouvelle instance du composant Form
. Les méthodes
suivantes attachent des entrées HTML à la définition de ce formulaire. ->addText
sera rendu comme
<input type="text" name="name">
avec <label>Nom :</label>
. Comme vous l'avez
probablement deviné, ->addTextArea
sera rendu comme <textarea>
et ->addSubmit
comme <input type="submit">
. Il existe de nombreuses autres méthodes similaires, mais celles-ci suffisent pour
ce formulaire. Vous pouvez en lire plus dans la documentation.
Si le formulaire est déjà défini dans le presenter, nous pouvons le rendre (l'afficher) dans le template. Pour ce faire,
placez la balise {control}
à la fin du template qui affiche un article spécifique, dans
Post/show.latte
. Comme le composant s'appelle commentForm
(le nom est dérivé du nom de la méthode
createComponentCommentForm
), la balise ressemblera à ceci :
...
<h2>Ajouter un nouveau commentaire</h2>
{control commentForm}
Maintenant, si vous affichez la page de détail de l'article, vous verrez le nouveau formulaire de commentaire à la fin.
Sauvegarde dans la base de données
Avez-vous déjà essayé de remplir et de soumettre le formulaire ? Vous avez probablement remarqué que le formulaire ne fait rien. Nous devons attacher une méthode de rappel qui enregistrera les données soumises.
Sur la ligne avant return
dans la factory du composant commentForm
, placez la ligne suivante :
$form->onSuccess[] = $this->commentFormSucceeded(...);
L'écriture précédente signifie “après la soumission réussie du formulaire, appelez la méthode
commentFormSucceeded
du presenter actuel”. Cependant, cette méthode n'existe pas encore. Créons-la :
private function commentFormSucceeded(\stdClass $data): void
{
$id = $this->getParameter('id');
$this->database->table('comments')->insert([
'post_id' => $id,
'name' => $data->name,
'email' => $data->email,
'content' => $data->content,
]);
$this->flashMessage('Merci pour votre commentaire', 'success');
$this->redirect('this');
}
Nous plaçons cette méthode juste après la factory du formulaire commentForm
.
Cette nouvelle méthode a un argument, $data
, qui est un objet contenant les données soumises du formulaire. Nous
obtenons l'ID de l'article à partir des paramètres du presenter. Ensuite, nous insérons les données dans la table
comments
de la base de données.
Il y a encore deux autres méthodes qui méritent d'être expliquées. La méthode redirect('this')
redirige vers
la page actuelle. Il est conseillé de le faire après chaque soumission de formulaire réussie. Lorsque vous redirigez après une
soumission de formulaire, vous ne verrez pas le message Voulez-vous renvoyer les données du formulaire ?
que les
navigateurs affichent parfois. (En général, après avoir soumis un formulaire avec la méthode POST
, il devrait
toujours y avoir une redirection vers une action GET
.)
La méthode flashMessage()
sert à afficher un message à l'utilisateur sur le résultat d'une opération. Comme
nous redirigeons, le message ne peut pas être simplement transmis au template et rendu immédiatement. C'est pourquoi cette
méthode existe : elle enregistre le message pour qu'il soit affiché lors du prochain chargement de la page. Les messages flash
sont rendus dans le template principal app/Presentation/@layout.latte
et ressemblent à ceci :
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
{$flash->message}
</div>
Comme nous le savons déjà, les messages flash sont automatiquement transmis au template, nous n'avons donc pas besoin d'y penser beaucoup, cela fonctionne tout simplement. Pour plus d'informations, visitez la documentation.
Affichage des commentaires
C'est l'une de ces choses que vous allez adorer. Nette Database a une fonctionnalité géniale appelée Explorer. Vous souvenez-vous que nous avons délibérément créé les tables de la base de données en utilisant le stockage InnoDB ? Adminer a ainsi créé quelque chose appelé clés étrangères, qui nous épargnera beaucoup de travail.
Nette Database Explorer utilise les clés étrangères pour résoudre les relations entre les tables et, grâce à la connaissance de ces relations, peut créer automatiquement des requêtes de base de données.
Comme vous vous en souvenez sûrement, nous avons transmis la variable $post
au template en utilisant la méthode
PostPresenter::renderShow()
et nous voulons maintenant itérer sur tous les commentaires dont la valeur de la colonne
post_id
est identique à $post->id
. Nous pouvons y parvenir en appelant
$post->related('comments')
. Oui, c'est aussi simple que ça. Jetons un coup d'œil au code résultant :
public function renderShow(int $id): void
{
...
$this->template->post = $post;
$this->template->comments = $post->related('comments')->order('created_at');
}
Et le template :
...
<h2>Commentaires</h2>
<div class="comments">
{foreach $comments as $comment}
<p><b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">
{$comment->name}
</a></b> a écrit:</p>
<div>{$comment->content}</div>
{/foreach}
</div>
...
Notez l'attribut spécial n:tag-if
. Vous savez déjà comment fonctionnent les n:attributs
. Si vous
ajoutez le préfixe tag-
à l'attribut, la fonctionnalité ne s'applique qu'à la balise HTML, pas à son contenu.
Cela nous permet de faire du nom du commentateur un lien uniquement s'il a fourni son e-mail. Ces deux lignes sont
identiques :
<strong n:tag-if="$important"> Bonjour ! </strong>
{if $important}<strong>{/if} Bonjour ! {if $important}</strong>{/if}