验证组不适用于表单

Posted

技术标签:

【中文标题】验证组不适用于表单【英文标题】:Validations Groups doesn't working with forms 【发布时间】:2021-11-10 08:08:09 【问题描述】:

我正在尝试在我的 symfony 项目上设置组验证。 当我更新一个实体时,我只需要验证一些字段。当我创建一个实体时,我只需要验证一些其他的字段。

服务:

$form = $this->formFactory->createNamed('form', FormType::class, $entity, ['validation_groups' => ['update']]);

表格:

class FormType extends AbstractType

    public function buildForm(FormBuilderInterface $builder, array $options)
    
        $builder
            ->add('user', EntityType::class, [
                'class' => User::class,
                'validation_groups' => ['create']
            ])
            ->add('number', EntityType::class, [
                'class' => Numbers::class,
                'validation_groups' => ['create', 'update']
            ])
            ->add('phone', TextType::class, [
                'validation_groups' => ['create', 'update']
            ])
        ;
    

    public function configureOptions(OptionsResolver $resolver)
    
        $resolver->setDefaults([
            'data_class' => Phones::class,
            'allow_extra_fields' => true,
            'validation_groups' => ['create', 'update'],
            'cascade_validation' => true,
        ]);
    

但是,当我提交表单时,“用户”字段仍然有效。

"form":"user":748,"number":"9.2","phone":"0x xx xx xx xx"

"id":957,"error":"Expected argument of type \"App\\Entity\\User\", \"null\" given at property path \"user\"."

【问题讨论】:

【参考方案1】:

您无需在字段上指定validation_groups。 默认情况下,传递到表单选项的组应用于所有字段。

# Service 1
// Only 'create' group will be validated
$this->formFactory->createNamed('form', FormType::class, $entity, ['validation_groups' => ['create']]);

# Service 2
// Only 'create' and 'update' group will be validated
$this->formFactory->createNamed('form', FormType::class, $entity, ['validation_groups' => ['create', 'update']]);

# Form
class FormType extends AbstractType

    public function buildForm(FormBuilderInterface $builder, array $options)
    
        $builder
            ->add('user', EntityType::class, [
                'class' => User::class,
                // 'validation_groups' => ['create']
            ])
            ->add('number', EntityType::class, [
                'class' => Numbers::class,
                // 'validation_groups' => ['create', 'update']
            ])
            ->add('phone', TextType::class, [
                // 'validation_groups' => ['create', 'update']
            ])
        ;
    

    public function configureOptions(OptionsResolver $resolver)
    
        $resolver->setDefaults([
            'data_class' => Phones::class,
            'allow_extra_fields' => true,
            // 'validation_groups' => ['create', 'update'],
            'cascade_validation' => true,
        ]);
    

但是,这看起来不像是表单验证错误(违规)。 Expected argument of type \"App\\Entity\\User\", \"null\" given at property path \"user\" 表示,传递给“用户”字段的值为空(未设置)。 当表单用于“创建”时,您应该省略“用户”字段。

解决方案一:

// add option 
$resolver->setDefaults([
    'data_class' => Phones::class,
    // ...
    'addUserField' => null,
]);

// in service pass this option
$this->formFactory->createNamed('form', FormType::class, $entity, [
   'validation_groups' => ['create'],
   'addUserField' => true
]);

// use condition in form to add field only if option is passed with true value
if($options['addUserField'] === true) 
    $builder->add('user', EntityType::class, [class' => User::class]);

$builder
   ->add('number'/** ... */)
   ->add('phone'/** ... */)
;

解决方案 2:

创建 2 种表单类型 FormTypeCreateFormTypeUpdate。跳过FormTypeUpdate 中的“用户”字段。您也可以从 FormTypeUpdate 扩展 FormTypeCreate

class FormTypeUpdate extends AbstractType

    public function buildForm(FormBuilderInterface $builder, array $options)
    
        $builder
            ->add('number', EntityType::class, [
                'class' => Numbers::class,
            ])
            ->add('phone', TextType::class)
        ;
    
    //...


//
class FormTypeCreate extends FormTypeUpdate

    public function buildForm(FormBuilderInterface $builder, array $options)
    
        $builder->add('user', EntityType::class, [
            'class' => User::class,
        ])
        parent::buildForm($builder, $options); // adds 'number' and 'phone' fields
    
    //...

【讨论】:

以上是关于验证组不适用于表单的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC 表单验证不适用于嵌套的复杂类型

Select2 不适用于动态添加的表单组

Symfony2 - 验证不适用于嵌入式表单类型

Yii 客户端验证不适用于 ajax 加载的表单

Laravel 表单请求验证规则“必需”不适用于空值

表单验证不适用于 Ionic 2 中的 Angular 2 FormBuilder