Symfony : Gérer un formulaire dans un composant
Dans un projet Symfony, comment gérer la validation d’un formulaire lorsqu’il est dans un composant ? C’est la question que l’on m’a posé cette semaine la semaine dernière (le temps passe vite…).
Tout d’abord, qu’est-ce qu’un composant dans Symfony ? Il s’agit en quelque sorte d’une action qui est réutilisable entre les différents modules de l’application. A la différence des « partials », qui sont « que » des templates, les composants contiennent de la logique : le plus souvent, récupérer un ou plusieurs modèles.
Pour revenir à la question, le problème n’est pas de gérer la validation à proprement parler, Symfony va s’en occuper grâce au forms framework mais plutôt de savoir où envoyer le visiteur une fois le formulaire soumis et comment, à la fin, le rediriger sur la page initiale, celle où il a rempli le formulaire.
Une solution possible est de créer une action spécifique pour valider le formulaire et d’ajouter un champ caché « referer » contenant l’url de la page initiale. Dans le fonctionnement, c’est relativement simple, le formulaire du composant pointe vers l’action et lorsque les données saisies sont valides, l’utilisateur est redirigé vers le valeur du champ « referer ».
Pour les intéressés, vous trouverez ci-dessous le contenu des différents fichiers pour l’utilisation d’un formulaire en composant. C’est prévu pour fonctionner avec Symfony 1.2.
- Le formulaire (lib/form/TestForm.class.php)
< ?php class TestForm extends sfForm { public function configure() { $this->setWidgets(array( 'name' => new sfWidgetFormInput(), 'referer' => new sfWidgetFormInputHidden(), )); $this->setValidators(array( 'name' => new sfValidatorString(), 'referer' => new sfValidatorString(array('required' => false)), )); $this->widgetSchema->setNameFormat('test-form[%s]'); } }
- Le composant (apps/frontend/modules/mymodule/actions/components.class.php)
< ?php class mymoduleComponents extends sfComponents { public function executeTestForm(sfWebRequest $request) { $this->form = new TestForm(array( 'referer' => $request->getUri() )); } }
- Le template du composant (apps/frontend/modules/mymodule/templates/_TestForm.php)
<h2>My Form</h2> <form action="<?php echo url_for('test-form') ?>" method="post"> <table> < ?php echo $form ?> </table> <input type="submit" value="Send" /> </form> - L’action (apps/frontend/modules/mymodule/actions/actions.class.php)
< ?php class mymoduleActions extends sfActions { public function executeTestForm(sfWebRequest $request) { $this->form = new TestForm(array( 'referer' => $request->getUri() )); if ($request->isMethod('post')) { $this->form->bind($request->getParameter($this->form->getName())); if ($this->form->isValid()) { $this->redirect( $this->form->getValue('referer') ? $this->form->getValue('referer') : 'homepage' ); } } } }
- Le template de l’action (apps/frontend/modules/mymodule/templates/TestFormSuccess.php)
< ?php include_partial('TestForm', array('form' => $form)) ?>
- La règle de routage (apps/frontend/config/routing.yml)
test-form: url: /test-form param: { module: mymodule, action: TestForm }
Une fois tous les fichiers créés, il ne reste plus qu’à inclure le composant dans un template, par exemple apps/frontend/layout.php, en ajoutant ceci :
< ?php include_component('mymodule', 'TestForm') ?>
Ici, le formulaire ne sert absolument à rien, la valeur saisie n’est pas utilisée. Il s’agit juste d’un exemple pour montrer le principe.
Note : Attention Wordpress à ajouté un espace entre < et ?php
Bonjour,
Tu devrais passer la valeur du referer comme option, comme cela ton formulaire n’est pas lie au sfContext. C’est mieux pour les tests unitaires …
Bonjour,
Merci ! J’ai modifié l’article en conséquence.
Merci pour le post, c’est bon mangez-en !