How to add validators on the fly in Symfony2?

11,914

Solution 1

Oh well, found a solution myself after a few experiments.

I'm going to leave this question unanswered for a couple of days as one can post a better solution, that would be really really welcome :)

In particular, i found the new FormError part redundat, don't know if there is a better way to add the error to the form. And honestly, don't know why new Form\CallbackValidator works while new CallbackValidator won't.

So, don't forget to add use statements like these:

use Symfony\Component\Form as Form, // Mendatory
    Symfony\Component\Form\FormInterface,
    Symfony\Component\Validator\Constraints\MinLength,
    Symfony\Component\Validator\Constraints\MinLengthValidator;

And the callback is:

$validation = function(FormInterface $form) {

     // If $data is null then the field was blank, do nothing more
    if(is_null($data = $form->getData())) return;

    // Create a new MinLengthValidator
    $validator = new MinLengthValidator();

    // If $data is invalid against the MinLength constraint add the error
    if(!$validator->isValid($data, new MinLength(array('limit' => 3)))) :

        $template   = $validator->getMessageTemplate();    // Default error msg
        $parameters = $validator->getMessageParameters();  // Default parameters

         // Add the error to the form (to the field "password")
        $form->addError(new Form\FormError($template, $parameters));

    endif;

};

Well, and this is the part i can't understand (why i'm forced to prefix with Form), but it's fine:

$builder->get('password')->addValidator(new Form\CallbackValidator($validation));

Solution 2

addValidator was deprecated and completly removed since Symfony 2.3.

You can do that by listening to the POST_SUBMIT event

$builder->addEventListener(FormEvents::POST_SUBMIT, function ($event) {
    $data = $event->getData();
    $form = $event->getForm();

    if (null === $data) {
        return;
    }
    if ("Your logic here") {
        $form->get('new_password')->addError(new FormError());
    }
});
Share:
11,914
gremo
Author by

gremo

Updated on June 16, 2022

Comments

  • gremo
    gremo almost 2 years

    I've a password form field (not mapped to User password) to be used in a change password form, along with two other (mapped) fields, first and last.

    I've to add validators on the fly: if value for password is blank then no validation should occur. Otherwise a new MinLength and MaxLength validators should be added.

    Here is what i've done so far: create the repeated password field, add a CallbackValidator and return if $form->getData() is null.

    Then, how can i add validators for minimum and maximum length to $field?

        $builder = $this->createFormBuilder($user);
    
        $field = $builder->create('new_password', 'repeated',  array(
                'type'          => 'password',
                'first_name'    => 'Password',
                'second_name'   => 'Confirm password',
                'required'      => false,
                'property_path' => false // Not mapped to the entity password
            ));
    
        // Add a callback validator the the password field
        $field->addValidator(new Form\CallbackValidator(function($form) {
            $data = $form->getData();
    
            if(is_null($data)) return; // Field is blank
    
            // Here password is provided and match confirm, check min = 3 max = 10
    
        }));
    
        // Add fields to the form
        $form = $builder
            ->add('first', 'text', array('required' => false)) // Mapped
            ->add('last',  'text', array('required' => false)) // Mapped
            ->add($field)                                      // Not mapped
            ->getForm();
    
  • Cerad
    Cerad about 12 years
    Just add: use Symfony\Component\Form\CallbackValidator; to drop the form prefix. PHP namespaces work well but they are not "package" oriented like java. Best to just has a use statement for each class used.
  • Athlan
    Athlan almost 11 years
    Unfortunately, I receive: Call to undefined method Symfony\Component\Form\FormBuilder::addValidator when i call $builder->get('password')->addValidator( ... )
  • DavidPostill
    DavidPostill over 9 years
    This does not answer the original quesion. It looks like it should be a comment to a comment on one the the other answers.
  • ghaliano
    ghaliano over 9 years
    He does, as i have migrate some projects to the symfony2.5 version, addValidator is no longer availbale so using $builder->addEventListener(FormEvents::POST_BIND, function ($event) unstead of $field->addValidator do the job
  • DavidPostill
    DavidPostill over 9 years
    The original question was for symfony2 not 2.3 or 2.5
  • ghaliano
    ghaliano over 9 years
    ok you right, maybe my question should be a comment reply but there are some difference between version like this one
  • Radu
    Radu over 9 years
    FormEvents::POST_SET_DATA to make sure you have everything you need before submit