如何在Symfony2中动态添加验证器?

如何在Symfony2中动态添加验证器?

问题描述:

我有一个password表单字段(映射到User密码的 not )以及两个其他(映射的)字段firstlast.

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.

我必须即时添加验证器:如果密码的值为空,则不进行验证.否则,应添加新的 MinLengthMaxLength验证器.

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.

这是我到目前为止所做的:创建重复的password字段,如果$form->getData()null,则添加CallbackValidatorreturn.

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

然后,如何为$ field添加最小和最大长度的验证器?

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();

哦,好了,经过几次实验,我自己找到了解决方案.

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 :)

尤其是,我发现了new FormError部分冗余,不知道是否有更好的方法将错误添加到表单中.老实说,不知道为什么new Form\CallbackValidator起作用而new CallbackValidator不能起作用.

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.

因此,不要忘记添加如下的use语句:

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;

回调是:

$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;

};

好吧,这是我无法理解的部分(为什么我必须加Form作为前缀),但这很好:

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));