如何在 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
遗漏了与添加我假设的字段相关的代码:
- 您没有直接通过
data_class
将表单关联到实体,而是在您的控制器中设置值
repeated
类型有 required => true
作为一个选项,用于验证密码
- 传递给表单生成器的
$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;
}
我有一个包含许多字段和验证组的表单,这些字段也包含一些视图数据转换器。
我需要部分取消验证表单 (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
遗漏了与添加我假设的字段相关的代码:
- 您没有直接通过
data_class
将表单关联到实体,而是在您的控制器中设置值 repeated
类型有required => true
作为一个选项,用于验证密码- 传递给表单生成器的
$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;
}