如何在 Symfony2 中禁用一个转换器验证错误 "dynamically"

How to disable one transformer validation error "dynamically" in Symfony2

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

我需要部分取消验证表单 (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');
        },
    ));
}

执行此操作时,表单将执行基本的完整性检查 (Disabling Validation) and the validation errors that coming from the transformers were still thrown (Creating the Transformer)。

使用 POST_SUBMIT 事件并阻止 ValidationListener from being called (Suppressing Form Validation):

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

    // ...
}

这对我来说不是一个解决方案,因为它意外地禁用了不仅仅是表单验证的东西。

问题是:如何“动态”禁用一个转换器验证错误?

示例:

我有一个表单字段 RepeatedType 属于 person 验证组,并且包含一个视图转换器 (RepeatedType), this transformer throws an exception when the values in the array aren't the same (ValueToDuplicatesTransformer)。

因此,即使验证组是 company,表单也会显示错误属于来自转换器的 RepeatedType 字段。

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

您无法真正停用来自 DataTransformer 的错误,这些错误是由 FormValidator 添加的,并且此行为不可自定义。这是非常合乎逻辑的,因为转换错误导致模型数据处于损坏状态。

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

因为 buildForm 遗漏了与添加我假设的字段相关的代码:

  1. 您没有直接通过 data_class 将表单关联到实体,而是在您的控制器中设置值
  2. repeated 类型有 required => true 作为一个选项,用于验证密码
  3. 传递给表单生成器的 $data 包含 repeated 字段的值。

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

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

也许最稳健的解决方案甚至有所不同,最好制作两个 FormTypes 而不是使用 groups。这将消除您在问题中描述的大部分复杂性。

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

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

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