2010-12-09 15 views
1

J'ai une SymfonyForm qui a 1: n embedForm (s). La forme principale et la classe embedForm ont leur propre PreValidation, qui implémente une validation conditionnelle. Une partie de la classe embedForm ressemble à ceci:PreValidation dans Symfony 1.4 pour embedForm avec sfValidatorCallback

private function configurePreValidators() { 
    $validator = new sfValidatorCallback(array('callback'=> array($this, 'preValidation'))); 
    $this->getValidatorSchema()->setPreValidator(new sfValidatorOr(array($validator))); 
} 

public function preValidation(sfValidatorCallback $validator, array $values){ 
... 
    $this->getValidator(self::SOME_FIELD)->setOption('required', false); 
... 
} 
public function configure() { 
    ... 
    $this->configurePreValidators(); 
    parent::configure(); 
} 

Le prévalidation de la forme principale est similaire.

Lorsque je soumets le formulaire, la prévalidation de la forme principale fonctionne correctement.

Dans le embedForm le « un_champ » obtient une validation d'erreur nécessaire, bien que je l'ai mis explicitement setOption (« nécessaire », false) dans la prévalidation du embedForm.

Y at-il quelque chose que je dois prendre en compte lorsque j'utilise la pré-validation dans un embedForm? Qu'en est-il de mergePreValidator? Des indices à ce sujet?

Merci d'avance!

Répondre

3

Le problème ici n'est pas que vos pré et post validateurs ne tirent pas - ils sont (ou du moins, ils devraient l'être). Le problème est que le validateur que vous modifiez est preValidate n'est pas celui référencé dans le schéma de validateur de niveau supérieur, c'est-à-dire le schéma de validation pour le formulaire de niveau supérieur.

Une solution: plutôt que de modifier le validateur en preValidate, effectuez simplement la validation:

public function preValidation(sfValidatorCallback $validator, array $values) 
{ 
    if (!$this->getValidator(self::SOME_FIELD)->isEmpty($values[self::SOME_FIELD]) 
    { 
    throw new sfValidatorErrorSchema(self::SOME_FIELD => new sfValdiatorError($validator, 'msg')); 
    } 
} 

Remarque, cette solution présente un danger: si vous modifiez le validateur pour un_champ intérieur du formulaire de niveau supérieur , il ne sera pas modifié dans ce pré-validateur et vice-versa.

Voyons pourquoi. Dans sfForm :: embedForm:

public function embedForm($name, sfForm $form, $decorator = null) 
{ 
    ... 
    $this->validatorSchema[$name] = $form->getValidatorSchema(); 
    ... 
} 

Symfony imbrique simplement les validateurs. C'est pourquoi pré et post sont toujours appelés. Pourquoi la référence change-t-elle? sfValidatorSchema :: offsetSet:

public function offsetSet($name, $validator) 
{ 
    ...  
    $this->fields[$name] = clone $validator; 
} 

Alors, quand un formulaire est intégré, le schéma de validateur est cloné. Ainsi, toute modification apportée aux validateurs à l'intérieur d'un formulaire intégré n'affecte pas le schéma du validateur de niveau supérieur.

+0

Merci pour vos explications ... – hasentopf

+0

Cela ne va pas aider dans ma classe de forme de haut niveau? Foreach ($ this-> getEmbeddedForm ('mes_membres_membrées') -> getEmbeddedForms() as $ form_id => $ form) { $ this-> mergePreValidator ($ form-> getValidatorSchema()); } ??? – hasentopf

+0

Non, sfForm :: embedForm est déjà en train de fusionner les schémas dans le code que j'ai collé ci-dessus. Les préValidateurs sont en train de modifier simplement la mauvaise instance de validateur. –

Questions connexes