Symfony2中是否有一种方法可以在使用级联验证时添加可选的嵌套表单?
换句话说,假设我有一个带有嵌套地址格式的用户表单(->add('adresse', new AddressType(), array('required' => false))
)。此地址不是必需的,但必须在用户指定('cascade_validation' => true
)时验证。
更新
相关实体和表格:
用户实体(Getters& Setters是经典的,Symfony生成的):
class User
{
[...]
/**
* @var \Address
*
* @ORM\OneToOne(targetEntity="Address", cascade="persist")
* @ORM\JoinColumn(
* name="address_id", referencedColumnName="id"
* )
*/
private $address;
[...]
}
地址实体是经典的,没有与用户的双向关系。
用户表单
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
[...]
->add('address', new AddressType(), array('required' => false))
[...]
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Xentia\FuneoBundle\Entity\User',
'cascade_validation' => true
));
}
public function getName()
{
return 'user';
}
}
地址嵌套表格是经典的
正如您所看到的,这是一个非常经典和简单的代码。唯一的特殊情况是地址是可选的。仅在地址先前已设置(并且因此存在于DB中并且与用户非空关系)并且用户想要取消设置(所有地址字段都为空)的情况下导致验证错误。 似乎如果相关地址没有实际的实例,它仍然是可选的。但是,如果地址的实例存在并且与用户链接,则它不再是可选的。
那么,它应该做什么:当用户更新他的个人资料时,如果有一个先前设置的地址并且他试图取消设置它,user->address
应该设置为NULL并且地址应该删除。
实际发生了什么:表单抛出一个验证错误,指出未设置地址字段。但是,由于地址是可选的,因此不应发生此类验证错误。而且,实际上,如果在用户更新其配置文件之前未设置地址,则不会发生这种情况,只有在先前设置了地址时才会发生。
答案 0 :(得分:1)
当用户更新他的个人资料时,如果有先前设置的地址并且他试图取消设置,则应将user->地址设置为NULL并删除该地址。
是的,你是对的,如果用户试图取消设置它就会被删除。在我们的评论中,您进一步澄清了一点:
“删除地址”按钮?在我看来,对用户来说太过分了......我认为没有理由这样做。如果用户未设置地址,则应自动删除该地址。软件必须对用户来说很容易,对开发者来说也很难,而不是相反。对我来说绝对不是一个好的解决方案。
这不是它应该如何运作的。由于用户之前已经创建了地址,因此删除此Address
实体是没有意义的,因为它的所有属性都是空的。如果您要删除用户,那么可能想要删除其地址。对于Doctrine,如果没有明确说明(或cascaded ),则无需删除关联。
您尝试实现的目标可能不会直接Constraint Configuration。您应该进行实体验证 内部 。
在Address
课程中设置Callbacks。可以是这样的:
/**
* @param ExecutionContextInterface $contextInterface
*/
public function validate(ExecutionContextInterface $contextInterface)
{
$country = ($this->country && $this->state);
$home = ($this->street && $this->zip);
if ($country || $home) {
//You can start validating your fields one by one as you wish
if ($this->country === null) {
$contextInterface->addViolationAt('country', 'Pick a Country, mercì');
}
[...]
}
//No property is set so we skip validation (they can be set as empty in the DB)
return;
}
您可以使用实体内部的验证constraints或总custom类来验证您的验证需求。