Symfony 2 Créer des formulaires avec Form 397
Gérer les formulaires avec Form Form : classe permettant de créer un formulaire à partir d'une entité Intérêt : Permet de mapper une entité pour modifier les instances de celle ci Normalise le développement Permet la création de composants réutilisables Fonctionnement : Le contrôleur récupère l'entité (couche objet) Créé un formulaire en lui passant l'objet pour sa modification Passe le formulaire à la vue, qui gère l'affichage des différents champs Lors de lavalidation, lecontrôleur reprend lamainpour effectuer la mise à jour 398
Méthode creatformbuilder(objet) : Gérer les formulaires avec Form Usine de composants, permet de fabriquer un objet Form Permet de créer un formulaire à partir d'un objet / d'une entité Méthode add() de FormBuilder : permettant de définir sous quelle forme mes propriétés p de l'objet sont représentées Elle permet par le biais de paramètres de générer les composants du formulaire Méthode getform() : Permet de récupérer l'objet Form créé Méthode createview() : 399 Créé la vue à partir de l'objet Form
Gérer les formulaires avec Form Exemple : Création d'un formulaire pour la création d'une potion Modification de la méthode newaction() du contrôleur PotionControleur public function newaction() { // création d'un objet potion $potion = new Potion(); Création du formulaire à partir de l'objet $potion 400 $form = $this->createformbuilder($potion) Création d'un champs text avec son label contenant le nom de la potion ->add("nom", "text", array('label' => 'Nom potion : ')) ->add("valider", "submit", array()) ->getform(); Récupération du Form Création d'un bouton de soumission du formulaire return $this->render( 'MmilesGauloisBundle::/pages/potion/newPotion.html.twig', array( 'formpotion' ot o => $form->createview() e ) ); Création de la vue
La vue : pages/potion/newpotion.html.twig : Gérer les formulaires avec Form {% extends 'MmilesGauloisBundle::base.html.twig' %} {% block title %}Création d'une potion{% endblock %} {% block page %} {{ form(formpotion) }} </div> {% endblock %} Résultat : 401 Le formulaire a bien été généré, il convient de le personnaliser en regard de l'identité visuelle retenue
Personnaliser le rendu La personnalisation du rendu est effectuée au niveau de la vue) On peut malgré tout passer des paramètres de css lors de la construction du formulaire L'affichage : {{ form(formpotion) }} Peut être décomposé en : {{ form_start(form) }} {{ form_widget(form) }} {{ form_errors(form) }} {{ form_end(form) }} Début du formulaire (correspond à la balise form) Composant(s) du formulaire Erreur(s) )liées au composant du formulaire Fin du formulaire 402
Structure du formulaire sous Twig : Personnaliser le rendu form() form_start() form_rows form_end() Tous lescomposants Chaque composant (une ligne) form_row() form_rest() Reste du formulaire (composants non utilisés) + un champs CSRF form_label() l() form_errors() form_widget() Label du composant Erreurs du composant Widget du composant (type de balise et contenu) 403
Personnalisation du rendu Personnalisation du formulaire de création d'une potion : 404 {% extends 'MmilesGauloisBundle::template.html.twig' %} {% block page %} Début du formulaire {{ form_start(formpotion)}} <div class="panel panel-default" id="pagepotion"> <div class="panel-heading"> <strong>création d'une potion</strong></div> <div class="panel-body"> <table class="table-hover table-striped col-md-12 col-sm-12 col-xs-12"> <tbody> <tr> <td> <div class="input-group"> <span class="input-group-addon"> {{ form_label(formpotion.nom)}} Label du champs nom </span> {{ form_widget(formpotion.nom, nom { Champs texte nom de la 'attr': { potion et ses caractéristiques 'class': 'form-control', 'placeholder' : 'Nom de la potion' } } )}}
Personnalisation du rendu Personnalisation du formulaire de création d'une potion : {{ form_errors(formpotion.nom)}} </div> </td> </tr> </tbody> </table> Balise des erreurs sur le champs nom de la potion </div> <div class="panel-footer"> {{ form_widget(formpotion.valider,{ Bouton de validation et ses 'attr': { caractéristiques 'class': 'btn btn-default'} } )}} </div> </div> Fin du formulaire {{ form_end(formpotion) }} {% endblock%} 405
CSRF Qu'est ce que le CSRF? Le champ CSRF, pour Cross Site Request Forgeries : Permet de vérifier que l'internaute qui valide le formulaire est bien celui qui l'a affiché. C'est un moyen de se protéger des envois de formulaires frauduleux C'est un champ que Symfony2 rajoute automatiquement à tous les formulaires, afin de les sécuriser Ce champ s'appelle _token dans vos formulaires On peut le voir en affichant la source HTML 406
Traitement du formulaire Lorsque le formulaire est soumis, le contrôleur reprend la main et effectue les mises à jour, à partir de la requête qui lui est envoyée par la vue On peut alors effectuer le traitement directement dans la même méthode, ou une autre (comme vu précédemment pour la méthode update()) Dans notre exemple, la mise à jour s'effectue sur la même méthode, la méthode update devient caduque On utilise donc plus qu'une méthode éh pour tout faire : newaction() 407
Traitement du formulaire Traitement de la requête du formulaire par le contrôleur Complément du contrôleur : PotionController.php méthode newaction() Deux parties : 1 partie : création du formulaire, envoi vers la page contenant le formulaire de création (en GET) 2 partie : traitement de la réception des données du formulaire pour création de la potion (en POST) On utilise la même technique qu'en PHP, lorsque l'on utilise un formulaire en PHP_SELF Structure de la méthode : newpotionaction() : On créé le formulaire Si l'on est en POST : traitement du formulaire 408 Sinon (on est en GET) : Affichage du formulaire
Structure de la méthode : newpotionaction() : Traitement du formulaire public function newaction(request $request) { Est on en POST? } Oui : Traitement du formulaire Redirection vers la liste des potions Non : Affichage du formulaire 1 partie traitement POST 2 partie affichage GET A noter : on passe la requête en paramètre à la méthode, ce qui facilite sa récupération Il faut spécifier dans le contrôleur l'appel de la classe Request, en entête de la classe : use Symfony\Component\HttpFoundation\Request; 409
Les routes : Traitement du formulaire # Gestion des potions -------------------------- mmilesgaulois_newpotion: path: /newpotion defaults: { _controller:mmilesgauloisbundle:potion:new } #mmilesgaulois_createpotion: # path: /createpotion # defaults: { #_controller:mmilesgauloisbundle:potion:create } # requirements: # _method: POST La route de création POST devient caduque 410
PotionController newaction() Contrôleur PotionController méthode newpotionaction() : public function newaction(request $request) { // création d'un objet potion $potion = new Potion(); Création du formulaire // Création de l'objet Form $form = $this->createformbuilder($potion) ->add( "nom", "text", array('label' => 'Nom potion : ')) ->add( "valider", "submit", array()) ->getform(); 411
PotionController newaction() // Traitement du formulaire appel de méthode en POST if ($request->ismethod('post')) { // Récupérer la requête du formulaire $form->handlerequest($request); // si le formulaire est valide if($form->isvalid()){ // Récupération des données du formulaire $donnees = $form->getdata(); // Chargement du nom provenant du formulaire $potion->setnom($donnees->getnom()); 1 partie traitement POST Les éléments de la requête sont récupérés avec la méthode handlerequest() sur la requête On récupère ensuite les données directement sur l'objet $form // Instanciation de l'entitymanager $em = $this->getdoctrine()->getmanager(); // On «persiste» l'entité $em->persist($potion); $em->flush(); // On redirige vers la liste des potions return $this->redirect($this->generateurl('mmilesgaulois_potion')); }else{echo "Form invalide<br/>";} } 412
PotionController newaction() 2 partie affichage GET // 2 partie du formulaire // Si on arrive sur cette séquence, c'est que l'on est pas passé // dans la partie POST du formulaire // On est donc en GET, on affiche le formulaire } return $this->render( 'MmilesGauloisBundle::/pages/potion/newPotion.html.twig', array('formpotion' => $form->createview()) ); 413
Modification d'une potion Traitement de la mise à jour / modification On pratique avec le même formulaire, mais à partir d'une potion existante PotionController.php / méthode modifaction() : public function modifpotionaction(request $request){ // Recherche de la potion concernée $repository = $this->getdoctrine() ->getrepository('mmilesgauloisbundle:potion'); $potion = $repository->find($request->get("id")); // Création du formulaire $form = $this->createformbuilder($potion) ->add("nom", "text", array( 'attr' => array('class' => "form-control"), 'label' => 'Nom potion : ')) ->add("valider", "submit", array( 'attr' =>array('class' => "btn btn-default"))) ->getform(); 414
Symfony 2 Modification d'une potion PotionController.php / méthode modifpotionaction() : // Traitement du formulaire POST if ($request->ismethod('post')) { // Récupérer la requête du formulaire $form->handlerequest($request); // si le formulaire est valide if ($form->isvalid()) { // en fait $form->getdata() permet de récupérer directement // la potion modifiée via l'objet form // on peut donc la sauvegarder directement via $form->getdata() $em = $this->getdoctrine()->getmanager(); $em->persist($form->getdata()); $em->flush(); // On redirige i vers la liste des potions return $this->redirect($this ->generateurl('mmilesgaulois_potion')); }else{ echo "Form invalide"; foreach ($form->geterrors() as $error){ echo $error->getmessage()."<br/>";} } } 415
Symfony 2 Modification d'une potion PotionController.php / méthode modifpotionaction() : // On redirige vers la liste des potions (Affichage du formulaire return $this->render('mmilesgauloisbundle:: /pages/potion/modifpotion.html.twig', twig' array( 'formpotion' => $form->createview() )); } 416
417 Symfony 2 Modification d'une potion La vue modifpotion.html.twig : {% extends 'MmilesGauloisBundle::template.html.twig' %} {% block page %} <form method="post" action="{{ path('mmilesgaulois _ modifpotion', {'id': potion.id}) }}"> <div class="panel panel-default" id="pagepotion"> <div class="panel-heading"> <strong>modification ti d'une potion</strong> t </div> <div class="panel-body"> <table class="table-hover table-striped col-md-12 col-sm-12 col-xs-12"> <div class="input-group"> <span class="input-group-addon"> {{ form_label(formpotion.nom)}}</span> nom)}}</span> {{ form_widget(formpotion.nom) }} </div> </div> <div class="panel-footer"> {{ form_widget(formpotion.valider) }} {{ form_rest(formpotion) rest(formpotion) }} </div> On ajoute form_rest (CSRF) sans lequel le formulaire risque d'être invalide
Type de champs disponibles pour les formulaires Form : Form types de champs Texte Choix Date et Divers Multiple Caché temps text choice date checkbox collection hidden textarea entity datetime file repeated csrf email courntry time radio integer language birthday money number password percent search url locale timezone 418