PreValidation in Symfony 1.4 for embedForm with sfValidatorCallback
I have a SymfonyForm which has 1:n embedForm(s). The main form and the embedForm class got their own PreValidation, which implements a conditional validation. A part of the EmbedForm class looks like this:
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();
}
The prevalidation of the main form is similar.
When I submit the form, the main form prevalidation works fine.
In the embed-Form the "SOME_FIELD" gets a required-validation-error although I set it explicit to setOption('required', false) in the preValidation of the embedForm.
Is there something what I have to开发者_如何学Go consider when I use pre-validation in an embedForm? What about mergePreValidator? Any hints about that?
Thanks in advance!
The issue here is not that your pre and post validators aren't firing -- they are (or at least, they should be). The issue is that the validator you are modifying is preValidate is not the one referenced in the top-level validator schema, i.e. the validator schema for the top-level form.
One solution: rather than modify the validator in preValidate, simply perform the 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'));
}
}
Note, this solution has some danger: if you modify the validator for SOME_FIELD inside of the top-level form, it will not be modified in this pre validator and vice-versa.
Let's look at why. In sfForm::embedForm:
public function embedForm($name, sfForm $form, $decorator = null)
{
...
$this->validatorSchema[$name] = $form->getValidatorSchema();
...
}
Symfony simply nests the validators. This is why pre and post still get called. Why does the reference change? sfValidatorSchema::offsetSet:
public function offsetSet($name, $validator)
{
...
$this->fields[$name] = clone $validator;
}
So when a form is embedded, the validator schema is cloned. Thus, any modifications to the validators inside of an embedded form do not affect the top-level validator schema.
精彩评论