如何在Symfony2中“动态”禁用一个变压器验证错误

时间:2022-10-22 18:17:56

I have a form with many fields and validation groups, these fields contains some view data transformers too.

我有一个包含许多字段和验证组的表单,这些字段也包含一些视图数据转换器。

I need suppress the validation form partially (Groups based on the Submitted Data):

我需要部分抑制验证表单(基于提交数据的组):

use AppBundle\Entity\Client;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

// ...
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'validation_groups' => function (FormInterface $form) {
            $data = $form->getData();

            if (Client::TYPE_PERSON == $data->getType()) {
                return array('person');
            }

            return array('company');
        },
    ));
}

When you do that, the form will still run basic integrity checks (Disabling Validation) and validation errors coming from transformers they are thrown still (Creating the Transformer).

当您这样做时,表单仍然会运行基本的完整性检查(禁用验证)和来自它们被抛出的变压器的验证错误(创建变压器)。

Use the POST_SUBMIT event and prevent the ValidationListener from being called (Suppressing Form Validation):

使用POST_SUBMIT事件并防止调用ValidationListener(抑制表单验证):

use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
        $event->stopPropagation();
    }, 900); // Always set a higher priority than ValidationListener

    // ...
}

It is not a solution for me, since accidentally disable something more than just form validation.

这对我来说不是一个解决方案,因为不小心禁用的不仅仅是表单验证。

The question is: How to disable one transformer validation error "dynamically"?

问题是:如何“动态地”禁用一个transformer验证错误?

Example:

例子:

I have a form field of RepeatedType belonging to person validation group and contains a view transformer (RepeatedType), this transformer throws an exception when the values in the array they are not the same (ValueToDuplicatesTransformer).

我有一个属于person验证组的重复类型的表单字段,并包含一个视图转换器(RepeatedType),当数组中的值不相同时,该转换器会抛出异常(ValueToDuplicatesTransformer)。

So, even when validation group is company, the form show errors belonging to RepeatedType field coming from transformer it.

因此,即使验证组是company,表单也显示来自transformer的属于重复类型字段的错误。

The question here is: How to disable the ValueToDuplicatesTransformer errors when validation group is not person?

这里的问题是:如何在验证组不是person时禁用ValueToDuplicatesTransformer错误?

3 个解决方案

#1


2  

Because the buildForm misses the code related to adding the fields I assume:

因为buildForm忽略了与添加字段相关的代码,我假设:

  1. you don't relate the form to an Entity via data_class directly, but set values in your controller
  2. 不直接通过data_class将表单与实体关联,而是在控制器中设置值
  3. the repeated type has required => true as an option and is there to validate a password
  4. 重复类型要求=>为true作为一个选项,并在那里验证密码
  5. the $data that is passed to the formbuilder contains a value for the repeated field.
  6. 传递给formbuilder的$数据包含重复字段的值。

The problem basically is that validation is triggered. If there is any data, then the type will always do it's basic validations (the repeated field should have the same value twice).

问题基本上是验证被触发了。如果有任何数据,那么类型将始终执行它的基本验证(重复字段应该具有相同的值两次)。

What you should do to solve this is do not pass the value to $data in the first place, and make sure required => false for the repeated field. Your form will only do the group validation after that, as you already explained.

要解决这个问题,首先要做的是不要将值传递给$data,并确保重复字段的required => false。正如您已经解释的那样,您的表单将只在此之后执行组验证。

Maybe the most robust solution is even different, and would it be best to make two FormTypes instead of using the groups. This will remove most of the complexity you describe in your question.

也许最健壮的解决方案是不同的,最好是创建两个formtype而不是使用组。这将消除您在问题中描述的大部分复杂性。

#2


0  

You can't really deactivate errors from a DataTransformer, these errors are added by FormValidator and this behavior is not customizable. This is quite logical since transformation errors leads to the model data being in a broken state.

您不能真正地从DataTransformer禁用错误,这些错误是由FormValidator添加的,这种行为是不可定制的。这很符合逻辑,因为转换错误导致模型数据处于破坏状态。

What I would do in this case is use 2 field instead of a repeated field with the second one with mapped => false and an event listener that add the error manually when needed.

在这种情况下,我要做的是使用2字段,而不是重复字段,第二个字段具有mapping => false,以及一个在需要时手动添加错误的事件监听器。

#3


0  

Maybe I'm wrong, but the validation group is not a right tool to solve the problem at all. The dependency of validation rules you want to solve is based on data, while the validation group is not about it, it's about the same data being validating differently depending on context.

也许我错了,但是验证组根本不是解决问题的正确工具。您想要解决的验证规则的依赖关系是基于数据的,而验证组不是基于数据的,而是基于不同的上下文对相同的数据进行不同的验证。

If you want to apply some rules only for person (or, the opposite, only for company), I would rather implement custom checking in Client Entity

如果您想只对个人(或者相反,只对公司)应用一些规则,我宁愿在客户端实体中实现自定义检查

namespace AppBundle\Entity;

class Client {
....
/**
* @Assert\IsTrue(message="Person should have a valid Title")
*/
public function isPersonTitleValid()
{
  return $this->type != Client::TYPE_PERSON || $this->isTitleValid();
}

public function isTitleValid()
{
  // Here implement your validation applicable only for person;
}

#1


2  

Because the buildForm misses the code related to adding the fields I assume:

因为buildForm忽略了与添加字段相关的代码,我假设:

  1. you don't relate the form to an Entity via data_class directly, but set values in your controller
  2. 不直接通过data_class将表单与实体关联,而是在控制器中设置值
  3. the repeated type has required => true as an option and is there to validate a password
  4. 重复类型要求=>为true作为一个选项,并在那里验证密码
  5. the $data that is passed to the formbuilder contains a value for the repeated field.
  6. 传递给formbuilder的$数据包含重复字段的值。

The problem basically is that validation is triggered. If there is any data, then the type will always do it's basic validations (the repeated field should have the same value twice).

问题基本上是验证被触发了。如果有任何数据,那么类型将始终执行它的基本验证(重复字段应该具有相同的值两次)。

What you should do to solve this is do not pass the value to $data in the first place, and make sure required => false for the repeated field. Your form will only do the group validation after that, as you already explained.

要解决这个问题,首先要做的是不要将值传递给$data,并确保重复字段的required => false。正如您已经解释的那样,您的表单将只在此之后执行组验证。

Maybe the most robust solution is even different, and would it be best to make two FormTypes instead of using the groups. This will remove most of the complexity you describe in your question.

也许最健壮的解决方案是不同的,最好是创建两个formtype而不是使用组。这将消除您在问题中描述的大部分复杂性。

#2


0  

You can't really deactivate errors from a DataTransformer, these errors are added by FormValidator and this behavior is not customizable. This is quite logical since transformation errors leads to the model data being in a broken state.

您不能真正地从DataTransformer禁用错误,这些错误是由FormValidator添加的,这种行为是不可定制的。这很符合逻辑,因为转换错误导致模型数据处于破坏状态。

What I would do in this case is use 2 field instead of a repeated field with the second one with mapped => false and an event listener that add the error manually when needed.

在这种情况下,我要做的是使用2字段,而不是重复字段,第二个字段具有mapping => false,以及一个在需要时手动添加错误的事件监听器。

#3


0  

Maybe I'm wrong, but the validation group is not a right tool to solve the problem at all. The dependency of validation rules you want to solve is based on data, while the validation group is not about it, it's about the same data being validating differently depending on context.

也许我错了,但是验证组根本不是解决问题的正确工具。您想要解决的验证规则的依赖关系是基于数据的,而验证组不是基于数据的,而是基于不同的上下文对相同的数据进行不同的验证。

If you want to apply some rules only for person (or, the opposite, only for company), I would rather implement custom checking in Client Entity

如果您想只对个人(或者相反,只对公司)应用一些规则,我宁愿在客户端实体中实现自定义检查

namespace AppBundle\Entity;

class Client {
....
/**
* @Assert\IsTrue(message="Person should have a valid Title")
*/
public function isPersonTitleValid()
{
  return $this->type != Client::TYPE_PERSON || $this->isTitleValid();
}

public function isTitleValid()
{
  // Here implement your validation applicable only for person;
}