Les formulaires
Les formulaires sont une partie importante des applications Web.
Ils permettent à nos utilisateurs d’interagir avec notre site.
Nous allons ici créer des commentaires pour nos articles.
Pour cela, un utilisateur va devoir Donner son nom, son email et bien sûr son commentaire.
Commençons par le HTML
Nous allons pour l’instant afficher nos commentaires en simple HTML, dans sur la page d’un article.
Intégrez le code HTMl ci-dessous dans la page d’un article.
<hr>
<div class="container">
<div class="row">
<h3 class="col-lg-8 col-md-10 mx-auto">2 Comments</h3>
</div>
<!-- Comments Form -->
<div class="col-lg-8 col-md-10 mx-auto">
<div class="card my-4">
<h5 class="card-header">Leave a Comment:</h5>
<div class="card-body">
<form>
<div class="form-group">
<label for="name">Name</label>
<input id="name" class="form-control form-control-sm" type="text">
</div>
<div class="form-group">
<label for="email">Email</label>
<input id="email" class="form-control form-control-sm" type="email">
</div>
<div class="form-group">
<label for="comment">Comment</label>
<textarea id="comment" class="form-control form-control-sm" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-secondary">Submit</button>
</form>
</div>
</div>
</div>
<div class="row">
<div class="media mb-4 mt-4 col-lg-8 col-md-10 mx-auto">
<div class="media-body">
<h5 class="mt-0">John Doe <small>2020-03-19</small></h5>
<blockquote>Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.</blockquote>
</div>
</div>
</div>
<div class="row">
<div class="media mb-4 mt-4 col-lg-8 col-md-10 mx-auto">
<div class="media-body">
<h5 class="mt-0">Foo Bar <small>2020-04-19</small></h5>
<blockquote>Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.</blockquote>
</div>
</div>
</div>
</div>
Avec ça, vous devriez avoir une section commentaires avec un formulaire et deux commentaires.
Rien de bien compliqué pour l’instant…
L’entité Comment
Créez une simple entité Comment
grâce à make:entity
avec les champs suivant
- name, string, 255, nullable: no
- email, string, 255, nullable: no
- createdAt, datetime, nullable: no
- comment, text, nullable: no
Puis faite en sorte que la table comment
soit créée en DB
Encore une fois, c’est du déjà vu.
Les relations
Ces commentaires vont être liés à un article.
On va parler de relation
entre un article et un commentaire.
En SQL, cela correspond à une clé étrangère, où chaque ligne de la table comment
va contenir l’id de l’article auquel
il est lié.
Avec Doctrine, le commentaire va avoir une propriété article
qui va contenir l’objet Article
associé.
Nous allons générer ça avec la commande make:entity
. Cette commande, permet non seulement de créer une nouvelle entité,
mais également d’en ajouter en cours de route ! Pour cela, exécutez la commande et comme nom d’entité, entrez à nouveau
Comment
.
Ajoutez la propriété article
de type relation
et lié à l’entité Article
.
La commande va vous proposer 4 types de relation qui sont ManyToOne, OneToMany, ManyToMany et OneToOne. Cette commande explique assez clairement le comportement de chaque type.
Choisissez le type attendu ici puis répondez no
à la première question et yes
à la deuxième puis appuyez sur
Entrée
jusqu’à sortir de la commande.
Observez attentivement l’entité Comment
mais également l’entité Article
.
Vous remarquerez que nous avons maintenant une propriété $article
dans Comment
et $comments
dans Article
avec
des getters, setters mais aussi des méthodes addComment
et removeComment
dans Article
.
Créez des fixtures pour les commentaires
Exécutez la commande make:fixtures
pour créer une classe CommentFixtures
Générez des fixtures pour les commentaires et les lier à un article grâce à la documentation sur les références dans les fixtures.
Affichons ces commentaires
Dans le template, affichez les commentaires dans le code HTML ajouté précédemment.
Pour rappel, chaque Article
possède une propriété comments
qui contient tous les commentaires liés à cet article.
Afficher le nombre de commentaires là où il est actuellement écrit 2 Comments
.
Regarder les requêtes effectuées par Doctrine dans le profiler.
Et maintenant, les formulaires
On commence par les dépendances composer require form validator security-csrf
En Symfony, les formulaires sont également gérés par des classes PHP.
Utilisez la commande make:form
et répondez Comment
aux deux questions.
La classe CommentType
a été générée dans src/Form
.
Ouvrez cette classe et observez son contenu.
Supprimez de cette classe ->add('createdAt')
et ->add('article')
car ces champs ne sont pas éditables par l’utilisateur.
Modifiez la configuration twig
pour utiliser le thème Bootstrap 4 pour les formulaires.
Par défaut, Symfony détecte automatiquement le type de champ <input>
à utiliser en HTML à partir de la configuration.
Ici il va générer un champ type="text"
pour name
et email
et un <textarea>
pour comment
.
Voyons ça dans twig !
Il faut tout d’abord créer le formulaire dans la méthode show
du controlleur.
$commentForm = $this->createForm(CommentType::class);
Sans oublier le use
pour CommentType
Et le passer à Twig en ajoutant dans le tableau de paramètres de la méthode render
[
...
'commentForm' => $commentForm->createView()
]
Vous avez maintenant une variable commentForm
dans le template qui contient la représentation Objet de votre formulaire
HTML.
Par exemple, les balises <form>
et </form>
sont respectivement remplacées dans twig par {{ form_start(commentForm) }}
et
{{ form_end(commentForm) }}
.
Et chaque champ du formulaire (name, email et comment) est accessible comme une propriété.
Et pour afficher les champs du formulaire, vous pouvez utiliser {{ form_row(commentForm.email) }}
.
Affichez ainsi tous vos champs sans oublier de retirer les champs HTML.
Actualisez la page, vous devriez voir votre formulaire, remplissez-le et soumettez le formulaire !
Rien ne se passe, c’est bien normal.
Observez le HTML généré grâce à la console de votre navigateur.
Création de nos nouveaux commentaires
Ajoutez le code suivant dans votre méthode show
, entre le createForm
et le return
.
// le formulaire prend la requête et va récupérer à lintérieur les champs
// remplis par le formulaire HTML
$commentForm->handleRequest($request);
// Si le formulaire a été soumis et est valide
if ($commentForm->isSubmitted() && $commentForm->isValid()) {
// on récupère l'objet Comment créé par le formulaire
/** @var Comment $comment */
$comment = $commentForm->getData();
// on associe le commentaire à l'article et on défini la date de création
$comment
->setArticle($article)
->setCreatedAt(new \DateTime())
;
// on recupère le l'EntityManager de Doctrine qui va nous servir à sauvegarder notre commentaire en base de données
$manager = $this->getDoctrine()->getManager();
// le persist dit a Doctrine de conidérer cet Objet comme un objet à sauvegarder en base, l'objet est donc maintenant
// géré par Doctrine
$manager->persist($comment);
// le flush dit à Doctrine d'exécuter les requêtes SQL permettant de créer/modifier les objets sur lesquels
// on appelé ->persist()
$manager->flush();
// redirige vers la page actuelle (la redirection permet d'éviter qu'en actualisant la page, cela soumette
// à nouveau le formulaire
return $this->redirectToRoute('show', ['id' => $article->getId()]);
}
Lisez attentivement les commentaires afin de comprendre ce morceau de code.
Il faut également injecter la Request
dans la méthode (cf TP routing).
Retournez sur votre page et remplissez à nouveau votre formulaire, vous devriez voir votre commentaire apparaître !
Essayez d’en ajouter un nouveau mais en mettant un adresse email invalide comme test
par exemple.
Ca marche ! Pas terrible….
Pou remédier à ça, remplacez ->add('email')
par ->add('email', EmailType::class)
.
Essayez à nouveau, le formulaire est maintenant de Type Email et attend donc une adresse email valide.
Mais cette validation est faite en HTML, pas terrible en terme de sécurité.
Avec la console navigateur, modifiez le type de l’<input>
par text
(Clic Droit sur l’input puis Inspecter).
Essayez de soumettre à nouveau, ça devrait marcher…
C’est là qu’intervient, la validation !
Symfony possède un mechanisme de validation très puissant, qui s’intègre parfaitement avec les formulaires !
Dans votre entité Comment
, modifiez votre code comme ceci.
/**
* @ORM\Column(type="string", length=255)
*
* @Assert\Email()
*/
private $email;
Et ajoutez l’import use Symfony\Component\Validator\Constraints as Assert;
Recommencez le test, il y a encore la validation HTML, modifiez à nouveau le champ grâce à la console navigateur pour le
mettre en type text
.
Réitérez l’expérience, cette fois-ci le formulaire est soumis à Symfony, mais une erreur générée par Symfony apparaît.
Cette fois-ci, aucun moyen de le contourner !
Pour tester la validation backend dans de meilleures condition, remplacer le form_start
dans twig par
{{ form_start(commentForm, {attr: {'novalidate': 'novalidate'}}) }}
.
Cela va avoir pour effet de désactiver la validation HTML et laisser faire Symfony.
A partir de la liste de toutes les contraintes existantes, ajouter de la validation sur ce formulaire, pour vous assurer de recevoir la données dans le format souhaité (taille minimale, maximale, non vide, etc).