【问题标题】:Symfony5 Custom Validator in FormType - Validate password field when check box is on表单类型中的 Symfony 5 自定义验证器 - 选中复选框时验证密码字段
【发布时间】:2020-08-16 14:57:29
【问题描述】:

我想根据复选框的值验证表单中的输入密码字段。如果值为 TRUE,则密码字段应为 NOTBlank 和 Equal first to second。这是我到目前为止所拥有的:

namespace App\Form;

use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;


class UsuarioFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('nombre',null,[
            'required'   => true,
            'constraints'=> [
                new NotBlank([
                    'message' => 'Escriba el nombre por favor',
                ]),
            ]
        ])
        ->add('apellido',null,[
            'required'   => true,
            'constraints'=> [
                new NotBlank([
                    'message' => 'Escriba el apellido por favor',
                ]),
            ]
        ])
        ->add('user_name',null,[
            'required'   => true,
            'empty_data' => '',
            'constraints'=> [
                new NotBlank([
                    'message' => 'Escriba el nombre de usuario por favor',
                ]),
            ]
        ])
        ->add('active', CheckboxType::class, [
            'required' => false
        ])
        ->add('email',EmailType::class,[
            'constraints' => [
                new Email([
                    'mode'=> 'html5',
                    'message' => 'El correo electrónico {{ value }} no es un correo electrónico válido',
                ]),
            ]
        ])        
        ->add('plainPassword', RepeatedType::class, [
            'type' => PasswordType::class,
            'invalid_message' => 'Los campos de contraseña deben ser iguales',
            'mapped' => false,
            'required'   => false,
            'constraints' => [
                new Length([
                    'min' => 6,
                    'minMessage' => 'Your password should be at least {{ limit }} characters',
                    // max length allowed by Symfony for security reasons
                    'max' => 4096,
                ]),
            ],
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => User::class,
            'constraints' => [
                new Callback([$this, 'validate']),
            ],
        ]);
    }
    public function validate($data, ExecutionContextInterface $context): void
    {
        if ($data['chk_passUpdate']){
            if (trim($data['plainPassword']['first']) == '' ) {
                $context->buildViolation('El campo de contraseña no puede estar en blanco')
                ->atPath('plainPassword')
                ->addViolation();
            }
            if ($data['plainPassword']['first'] != $data['plainPassword']['second'] ) {
                $context->buildViolation('Los campos de contraseña deben ser iguales')
                ->atPath('plainPassword')
                ->addViolation();
            }
        }
    }
}

此代码抛出异常:

传递给 App\Form\UsuarioFormType::validate() 的参数 1 必须是数组类型,给定对象,在 C:\Csi\CsiWorkspace\SynfonyTest\SymfonyTest\vendor\symfony\validator\Constraints 中调用\CallbackValidator.php 第 46 行

【问题讨论】:

  • 您确定方法签名正是您发布的那个吗?仅当第一个参数上存在“数组”类型提示时才应生成错误。无论如何,这里的第一个参数应该是User的实例,RepeatedType已经保证了重复字段的匹配,并且应该通过NotBlank约束检查非空。
  • 似乎在这部分“new Callback([$this, 'validate'])”中,var $this 指的是对象 $user(用户实体)。

标签: symfony symfony5


【解决方案1】:

一周后,我发现最好的解决方案是使用验证组。

所以我的代码会是这样的:

namespace App\Form;

use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\FormInterface;


class UsuarioFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('nombre',null,[
            'required'   => true,
            'constraints'=> [
                new NotBlank([
                    'message' => 'Escriba el nombre por favor',
                ]),
            ]
        ])
        ->add('apellido',null,[
            'required'   => true,
            'constraints'=> [
                new NotBlank([
                    'message' => 'Escriba el apellido por favor',
                ]),
            ]
        ])
        ->add('user_name',null,[
            'required'   => true,
            'empty_data' => '',
            'constraints'=> [
                new NotBlank([
                    'message' => 'Escriba el nombre de usuario por favor',
                ]),
            ]
        ])
        ->add('active', CheckboxType::class, [
            'required' => false
        ])
        ->add('password_update', CheckboxType::class, [
            'required'  => false,
            'mapped'    => false
        ])
        ->add('email',EmailType::class,[
            'constraints' => [
                new Email([
                    'mode'=> 'html5',
                    'message' => 'El correo electrónico {{ value }} no es un correo electrónico válido',
                ]),
            ]
        ])        
        ->add('plainPassword', RepeatedType::class, [
            'type' => PasswordType::class,
            'invalid_message' => 'Los campos de contraseña deben ser iguales',
            'mapped' => false,
            'required'   => false,
            'constraints' => [
                new Length([
                    'min' => 6,
                    'minMessage' => 'Your password should be at least {{ limit }} characters',
                    // max length allowed by Symfony for security reasons
                    'max' => 4096,
                ]),
                new NotBlank([
                    'message' => 'Escriba su contraseña',
                    'groups' => 'password_update'
                ]),
            ],
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => User::class,
            'validation_groups' => function(FormInterface $form){
                if ($form['password_update']->getData()){
                    return array('Default', 'password_update');
                }else{
                    return array('Default');
                }
            }

        ]);
    }

}

这样,当复选框打开时,表单将验证 2 个组(default 和 password_udpate)。如果它关闭,则仅验证默认组。

希望有一天这对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-21
    • 2011-07-24
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 2014-03-04
    相关资源
    最近更新 更多