tl; dr:
我的Person
实体表单上有一个未映射的字段,需要对其进行验证。我已经关注了这篇很棒的文章,但是我的用例略有不同,并且并未完全涵盖在本文中。
我正在制作自己的唯一约束,需要运行自定义查询来确定唯一性。要运行查询,我需要访问已提交的字段值以及原始Person
对象(因此,如果它是更新操作,则可以获取它的ID)。如果没有那个Person
对象,我将无法在唯一性查询期间将其从考虑中删除。
如果我在PersonType
类上应用验证器,如下所示:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver
->setDefaults(array(
'data_class' => 'CS\AcmeBundle\Entity\Person',
'constraints' => array(
new MyUniqueValidator(),
)
))
;
}
然后,验证器将传递整个Person
对象以执行验证。这对我没有帮助,因为提交的表单数据不会持久保存到Person
对象(这是我$form->isValid()
在控制器中调用后要处理的未映射字段)。
如果我直接将验证器应用于未映射的字段,请执行以下操作:
$builder
->add('myUnmappedField', 'text', array(
'mapped' => false,
'constraints' => array(
new MyUniqueValidator(),
)
),
))
然后,传递给验证器的对象只是独立的表单文本,而没有其他内容。我没有Person
通过唯一性查询执行的ID对象(如果它是更新操作)。
希望我已经正确解释了这一点。我是否有任何选择可以优雅地进行这种验证?
你说你有未映射的字段。如果将其映射到Person实体,会有所帮助吗?只需使用getter和setter方法在Person类中创建一个新属性,而不是ORM,因为你不希望它持久化。
如果你不想污染你的Person类,则还可以创建另一个复合类,该复合类将保存你当前未映射的字段和一个Person对象(然后将其映射)。当然,你将随后设置data_class以匹配新对象的名称空间。
以上两种解决方案都应与你那里的上层代码一起使用。请让我知道它有所帮助。
谢谢。我先在Person实体上添加了另一个属性,然后将form字段映射到该属性。这很好。
很高兴能为您提供帮助;)而且在将来,请始终记住,一种形式只能有一个基础对象。如果您需要多个对象或类似的对象,请制作另一个复合对象,它始终可以包含更多对象/属性:)
当然,这是可行的,但这不能是对所提问题的公认答案……问题并不能由此得到解决,只是被绕过了
这是可以接受的解决方法,但我同意@AlexK-这实际上不是解决方案或问题的答案。