Commentaires
Le blog a été déployé, nous avons écrit de très bons articles de blog et les avons publiés via Adminer. Les gens lisent le blog et sont très passionnés par nos idées. Nous recevons chaque jour de nombreux courriels élogieux. Mais à quoi servent tous ces éloges si nous ne les recevons que dans le courrier électronique, de sorte que personne d'autre ne peut les lire ? Ne serait-il pas préférable que les gens puissent commenter directement sur le blog afin que tout le monde puisse lire à quel point nous sommes géniaux ?
Rendons tous les articles commentables.
Création d'un nouveau tableau
Lancez à nouveau Adminer et créez une nouvelle table nommée comments
avec ces colonnes :
id
int, vérifier l'auto-incrément (AI)post_id
, une clé étrangère qui fait référence à la tableposts
name
varchar, longueur 255email
varchar, longueur 255content
textecreated_at
timestamp
Cela devrait ressembler à ceci :
N'oubliez pas d'utiliser le stockage de table InnoDB et cliquez sur Enregistrer.
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 notre page. Le Nette Framework offre un support impressionnant pour les formulaires. Ils peuvent être configurés dans un présentateur et rendus dans un modèle.
Nette Framework a un concept de composants. Un composant est une classe réutilisable ou un morceau de code, qui
peut être attaché à un autre composant. Même un présentateur est un composant. Chaque composant est créé à l'aide de la
fabrique de composants. Définissons donc la fabrique du formulaire de commentaires dans PostPresenter
.
protected function createComponentCommentForm(): Form
{
$form = new Form; // signifie Nette\Application\UI\Form
$form->addText('name', 'Your name:')
->setRequired();
$form->addEmail('email', 'Email:');
$form->addTextArea('content', 'Comment:')
->setRequired();
$form->addSubmit('send', 'Publish comment');
return $form;
}
Nous allons l'expliquer un peu. La première ligne crée une nouvelle instance du composant Form
. Les méthodes
suivantes permettent d'attacher des entrées HTML à la définition du formulaire. ->addText
sera rendu en tant
que <input type=text name=name>
, avec <label>Your name:</label>
. Comme vous l'avez
sans doute déjà deviné, le composant ->addTextArea
attache une balise <textarea>
et
->addSubmit
ajoute un <input type=submit>
. Il existe d'autres méthodes de ce type, mais c'est
tout ce que vous devez savoir pour le moment. Vous pouvez en apprendre davantage dans la
documentation.
Une fois le composant de formulaire défini dans un présentateur, nous pouvons le rendre (l'afficher) dans un modèle. Pour ce
faire, placez la balise {control}
à la fin du modèle de détail de l'article, dans Post/show.latte
.
Comme le nom du composant est commentForm
(dérivé du nom de la méthode createComponentCommentForm
),
la balise ressemblera à ceci
...
<h2>Post new comment</h2>
{control commentForm}
Maintenant, si vous consultez les détails d'un article, vous trouverez un nouveau formulaire pour poster des commentaires.
Sauvegarde dans la base de données
Avez-vous essayé de soumettre des données ? Vous avez peut-être remarqué que le formulaire n'effectue aucune action. Il est juste là, à l'air cool et ne fait rien. Nous devons attacher une méthode de rappel à ce formulaire, qui enregistrera les données soumises.
Placez la ligne suivante avant la ligne return
dans la fabrique du composant commentForm
:
$form->onSuccess[] = $this->commentFormSucceeded(...);
Elle signifie „après que le formulaire ait été soumis avec succès, appelez la méthode commentFormSucceeded
du présentateur actuel“. Cette méthode n'existe pas encore, alors 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('Thank you for your comment', 'success');
$this->redirect('this');
}
Vous devez la placer juste après la fabrique du composant commentForm
.
La nouvelle méthode a un argument qui est l'instance du formulaire soumis, créé par la fabrique de composants. Nous recevons
les valeurs soumises dans $data
. Et ensuite nous insérons les données dans la table de la base de données
comments
.
Il y a deux autres appels de méthode à expliquer. La redirection redirige littéralement vers la page actuelle. Vous devez le
faire à chaque fois que le formulaire est soumis, valide et que l'opération de rappel a fait ce qu'elle devait faire. En outre,
lorsque vous redirigez la page après avoir soumis le formulaire, vous ne verrez pas le message bien connu
Would you like to submit the post data again?
que vous pouvez parfois voir dans le navigateur. (En général, après
avoir soumis un formulaire par la méthode POST
, vous devriez toujours rediriger l'utilisateur vers une action
GET
).
Le message flashMessage
sert à informer l'utilisateur du résultat d'une opération quelconque. Comme il s'agit
d'une redirection, le message ne peut pas être transmis directement au modèle et rendu. Il y a donc cette méthode qui le stocke
et le rend disponible au prochain chargement de la page. Les messages flash sont rendus dans le fichier
app/UI/@layout.latte
par défaut, et cela ressemble à ceci :
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
{$flash->message}
</div>
Comme nous le savons déjà, ils sont transmis automatiquement au modèle, de sorte que vous n'avez pas besoin d'y penser trop, cela fonctionne tout simplement. Pour plus de détails , consultez la documentation.
Rendu des commentaires
Voici l'une des choses que vous allez adorer. La base de données Nette dispose d'une fonctionnalité sympa appelée Explorer. Vous vous souvenez que nous avons créé les tables en InnoDB ? Adminer a créé ce qu'on appelle des clés étrangères qui vont nous épargner une tonne de travail.
Nette Database Explorer utilise les clés étrangères pour résoudre les relations entre les tables, et connaissant les relations, il peut automatiquement créer des requêtes pour vous.
Comme vous vous en souvenez peut-être, nous avons passé la variable $post
au modèle dans
PostPresenter::renderShow()
et maintenant nous voulons itérer à travers tous les commentaires qui ont la colonne
post_id
égale à notre $post->id
. Vous pouvez le faire en appelant
$post->related('comments')
. C'est aussi simple que cela. Regardez le code résultant.
public function renderShow(int $id): void
{
...
$this->template->post = $post;
$this->template->comments = $post->related('comments')->order('created_at');
}
Et le modèle :
...
<h2>Comments</h2>
<div class="comments">
{foreach $comments as $comment}
<p><b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">
{$comment->name}
</a></b> said:</p>
<div>{$comment->content}</div>
{/foreach}
</div>
...
Remarquez l'attribut spécial n:tag-if
. Vous savez déjà comment fonctionne n: attributes
. Si vous
faites précéder l'attribut de tag-
, il n'enveloppera que les balises, et non leur contenu. Cela vous permet de
transformer le nom du commentateur en un lien s'il a fourni son adresse électronique. Les résultats de ces deux lignes sont
identiques :
<strong n:tag-if="$important"> Hello there! </strong>
{if $important}<strong>{/if} Hello there! {if $important}</strong>{/if}