Il est courant qu’un formulaire web nécessite des validateurs dynamiques, c’est à dire dépendant de certaines valeurs du formulaire lui même. Dans une des applications que j’ai écrite récemment une case à côcher permet à l’utilisateur de tester le formulaire et de ne pas enclencher l’action normale. Ainsi lorsque cette case à côcher est validée, un champs du formulaires n’est plus obligatoire, et un autre le devient.

Pour résoudre ce problème, une des solutions connue consiste à surcharger la méthode bind de la classe du formulaire, dérivée de sfForm, et de changer à la volée les validateurs.

Pour ma part je préfère exécuter ce changement dynamique de validateur dans le preValidator. Voici ce que cela donne:

 public function configure()
 {
   [...]
   $this->validatorSchema->setPreValidator(
     new sfValidatorCallback (
       array('callback' => array($this, 'isTest'))));
 }
 public function isTest($validator, $values)
 {
   if (isset($values'is_test')) {
     $this->validatorSchema['email_recipients']->addOption('required', false);
     $this->validatorSchema['test_recipient']->addOption('required', true);
   } else {
     $this->validatorSchema['email_recipients']->addOption('required', true);
     $this->validatorSchema['test_recipient']->addOption('required', false);
   }
   return $values;
 }

Le code est plus facile à maintenir: tout ce qui concerne la validation s’exécute uniquement dans des validateurs, sans passer par une méthode, bind qui n’a rien à voir avec ce processus.