Symfony Form utilisation avancée des Validateurs
Dans le cadre d'un projet Symfony, je me suis heurté à une problématique d'apparence simple : l'utilisateur doit pouvoir changer ses informations personnelles, dont son mot de passe.
La difficulté est apparue au moment de mettre en place les validateurs de formulaire.
Le formulaire contient les champs suivants :
- nom
- prénom
- mot de passe actuel
- nouveau mot de passe
- confirmation de nouveau mot de passe
L’utilisateur doit pouvoir changer son nom ou son prénom sans forcément changer son mot de passe.
Il n'est pas non plus envisageable de pré-remplir le champ mot de passe actuel.
Pour pouvoir changer le mot de passe, il est nécessaire de connaitre l'ancien.
Il faut donc faire les contrôles suivants :
1. Si le champ nouveau mot de passe est rempli, alors le champ confirmation de nouveau mot de passe doit contenir la même chose
2. Si le champ nouveau mot de passe est rempli, alors le champ mot de passe actuel ne doit pas être vide. Autrement dit : les champs mot de passe actuel et nouveau mot de passe doivent être simultanément remplis ou bien simultanément vide.
3. Si le champ mot de passe actuel est rempli alors, il doit effectivement contenir le bon mot de passe
On peut résumer comme ceci :
(new_password == retype_new_password) && ( ( (current_password != '') && (new_password != '') && (current_password == 'CORRECT_CURRENT_PASSWORD') ) || ( (current_password == '') && (new_password == '') ) )
Avec les validateurs en place, cela donne ceci :
$this->mergePostValidator( new sfValidatorAnd( array( new sfValidatorSchemaCompare( 'password', sfValidatorSchemaCompare::EQUAL, 'retype_password', array(), array('invalid' => 'Les deux nouveaux mots de passe doivent etre identique') ), new sfValidatorOr( array( new sfValidatorAnd( array( new sfValidatorSchemaFilter('password', new sfValidatorString(array('required' => true),array('required'=>'Ce champ est obligatoire'))), new sfValidatorSchemaFilter('old_password', new sfValidatorString(array('required' => true),array('required'=>'Ce champ est obligatoire'))), new sfValidatorSchemaFilter('old_password', new sfValidatorCallback(array('callback' => array($this->getObject(),'checkPasswordValidator')))), ), array('halt_on_error' => true) ), new sfValidatorAnd( array( new sfValidatorSchemaFilter('password', new sfValidatorRegex(array('pattern' => '/^$/','required' => false),array('invalid' => ' '))), new sfValidatorSchemaFilter('old_password', new sfValidatorRegex(array('pattern' => '/^$/','required' => false),array('invalid' => ' '))) ) ) ) ) ), array('halt_on_error' => true) ) );
Les deux difficultés auxquelles je me suis retrouvé confronté sont les suivantes :
- contrôle de deux champs simultanément (tous les deux remplis ou tous les deux vides)
- vérifier que le mot de passe actuel rentré est le bon
Contrôler deux champs simultanéments
Pour résoudre le premier problème, je me suis basé sur les validateurs suivants.
Ce sont des 'supers-validateurs' dont le fonctionnement est un peu différents des validateurs habituels.
mergePostValidator
mergePostValidator ($validator)
Le validateur mergePostValidator permet d'ajouter un validateur après le passage de tous les autres validateurs. Les données sont ainsi déjà vérifiées et nettoyées.
sfValidatorAnd
sfValidatorAnd($validators, $options, $messages)
sfValidatorAnd permet d’agréger plusieurs validateurs avec un opérateur logique ET
sfValidatorOr
sfValidatorOr($validators, $options, $messages)
sfValidatorAnd permet d’agréger plusieurs validateurs avec un opérateur logique OU
sfValidatorSchemaCompare
sfValidatorSchemaCompare($leftField, $operator, $rightField, $options, $messages)
sfValidatorSchemaCompare sert à comparer les valeurs de deux champ d'un formulaire
sfValidatorSchemaFilter
sfValidatorSchemaFilter($field, $validator, $options, $messages)
sfValidatorSchemaFilter permet d'ajouter à la volée un validateur pour un champ donné. C'est très pratique lors de l’utilisation d'un PostValidateur
Vérifier un champ avec une donnée externe au formulaire
Pour le second problème il me fallait déporter le contrôle du mot de passe
sfValidatorCallback
sfValidatorCallback($options, $messages)
Ce validateur, plus classique, permet en effet de désigner un fonction à appeler qui se chargera de valider la donnée.
Je peux ainsi confier la responsabilité à une méthode de mon objet User de vérifier que le mot de passe saisie est le bon.
Avencinlect Thursday 28 July à 13h05
beaucoup appris
rim2004m Tuesday 18 March à 10h07
bonjour,
je suis encore débutante en symfony, je veux savoir comment tester si un champs dans un formulaire est bien rempli..
s'il vous plait je veux une réponse claire..
merci d'avance