【发布时间】:2018-08-15 16:10:46
【问题描述】:
我不得不将我的一个项目从 symfony 2.8 升级到 symfony 3.4,我注意到验证过程发生了巨大变化。
为了简化,假设我有一个 User 实体,其中包含许多 Addresses 实体。 当我创建/更新我的用户时,我希望能够添加/删除/更新任意数量的地址。所以在symfony 2.8中我遇到了这种情况
用户
我使用注释验证器
src/AppBundle/Entity/User.php
//...
class User
{
//...
/**
* @Assert\Count(min=1, max=10)
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Address", mappedBy="user", cascade={"persist", "remove"})
*/
protected $addresses;
//...
}
用户表单
src/AppBundle/Form/UserForm.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// ...
->add('addresses', CollectionType::class, [
'type' => AddressType::class,
'cascade_validation' => true,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
])
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
'cascade_validation' => true,
'validation_groups' => // User's logic
]);
}
地址
src/AppBundle/Entity/Address.php
//...
class Address
{
//...
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="user")
*/
protected $user;
/**
* @Assert\NotBlank(groups={"zipRequired"})
* @ORM\Column(type="text", nullable="true")
*/
protected $zipCode;
//...
}
地址表格
src/AppBundle/Form/AddressForm.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// ...
->add('zipCode', TextType::class)
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults([
'data_class' => Address::class,
'cascade_validation' => true,
'validation_groups' => function(FormInterface $form) {
/** @var Address $data */
$data = $form->getData();
$validation_groups = [];
// Simplified here, it's a service call with heavy logic
if ($data->doesRequireZip()) {
$validation_groups[] = 'zipRequired';
}
return $validation_groups;
},
]);
}
在 symfony 2.8 中
在添加的 3 个地址中,两个必须有效 zipRequired 组,一个不有效。我工作!
在 symfony 3.4 中
我在 User::$zipCode 声明中添加了 @Assert\Valid() 并删除了 'cascade_validation' => true(不在方法 configureOptions 但它似乎未使用),因为它已被弃用。
但现在添加了 3 个地址,其中两个必须验证 zipRequired 组,一个不能:只使用用户的类验证器组,所以我可以验证包含不连贯数据的表单!
我检查了 xdebug 并调用了 AddressForm 中的 validator_groups 回调,但没有调用验证器。
我测试了这里描述的解决方案:Specify different validation groups for each item of a collection in Symfony 2?,但它不能再工作了,因为在 symfony 3.4 中 cascade_validation 在属性上抛出错误
在我的情况下,所涉及的逻辑过于繁重,无法使用此处描述的解决方案广告 Specify different validation groups for each item of a collection in Symfony 3?,因为在单个方法中重写整个 validation_groups 回调非常无效,并且它将组应用于所有子实体。
@Assert\Valid 和 cascade_validation 的行为不同,有没有办法在 symfony 3.4 中处理嵌入表单的单个实体 validation_groups 或者该功能肯定消失了?
【问题讨论】:
-
你修复了吗?我在 sf 5.1 遇到完全相同的问题
-
刚刚发现他们会尊重根表单上添加的任何验证组,也许子表单上的回调运行并返回正确的组列表,它们在某种程度上被根表单的验证组覆盖.
-
可悲的是,他们称其为功能:github.com/symfony/symfony/issues/31441 我能找到的唯一方法是添加回调
标签: php forms symfony validation symfony-3.4