现在我已经成功使用了验证组,但现在我遇到了验证组和嵌套映射实体。
我将通过一个简化的例子来解释这个问题。
我的实体:地址,损坏,设备
/**
* @ORM\Entity()
*/
class Address extends ...
{
/**
* @var string
* @ORM\Column(type="string", name="postcode", nullable=true)
* @Assert\NotBlank(
* groups={
* "damage_responsible_address",
* "appliance_repairer_address",
* })
*/
private $postcode;
...
/**
* @ORM\Entity()
*/
class Damage extends ...
{
/**
* @var boolean
* @ORM\Column(type="boolean", name="responsible", nullable=true)
* @Assert\NotBlank(groups={"damage"})
*/
private $responsible;
/**
* @ORM\OneToOne(targetEntity="Address", cascade={"persist","remove"})
* @ORM\JoinColumn(name="responsible_address_id", referencedColumnName="id")
* @Assert\Valid()
*/
private $responsibleAddress;
/**
* @ORM\ManyToMany(targetEntity="Appliance", orphanRemoval=true, cascade={"persist", "remove"})
* @ORM\JoinTable(name="coronadirect_cuzo_home_damage_appliances",
* joinColumns={@ORM\JoinColumn(name="damage_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="appliance_id", referencedColumnName="id")}
* )
*/
private $appliances;
...
/**
* @ORM\Entity()
*/
class Appliance extends ...
{
/**
* @var boolean
* @ORM\Column(type="boolean", name="to_repair", nullable=true)
* @Assert\NotBlank(groups={"appliance"})
*/
private $toRepair;
/**
* @ORM\OneToOne(targetEntity="Address", cascade={"persist","remove"})
* @ORM\JoinColumn(name="repairer_address_id", referencedColumnName="id")
* @Assert\Valid()
*/
private $repairAddress;
...
要定义我的表单,我使用AddressType,DamageType和ApplianceType:
class DamageType extends ...
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('appliances', 'collection', array(
'type' => 'home_damage_appliance_type',
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'options' => array(
'cascade_validation' => true,
)
));
$builder->add('responsible', 'choice', array(
'choices' => $this->getYesNoChoiceArray(),
'expanded' => true,
'multiple' => false,
));
$builder->add('responsibleAddress', 'address_type', array(
'required' => true
));
...
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Damage',
'cascade_validation' => true,
'validation_groups' =>
function(FormInterface $form) {
$groups = array('damage');
if ($form->getData()->getResponsible() == true) {
$groups[] = 'damage_responsible_address';
}
return $groups;
}
));
}
我在表单中将责任设置为true时添加damage_responsible_address组。 否则我不希望验证地址。
class ApplianceType extends ...
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('toRepair', 'choice', array(
'choices' => $this->getYesNoChoiceArray(),
'expanded' => true,
'multiple' => false,
));
$builder->add('repairAddress', 'address_type', array(
'required' => true
));
...
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Appliannce',
'cascade_validation' => true,
'validation_groups' =>
function(FormInterface $form) {
$groups = array('appliance');
if ($form->getData()->getToRepair() == true) {
$groups[] = 'appliance_repairer_address';
}
return $groups;
}
));
}
与之前相同,当toRepair为true时,我想验证地址。
出了什么问题?
我对Damage的责任是真的,而且设备toRepair是假的,表格确实会在负责的地址上给出验证错误,但也会在设备地址上给出验证错误。
对于arround的另一种方式相同:当设备地址无效(toRepar为true)时,trustedAddress也无效(即使负责人为假)。
地址验证组不会查看它们的定义形式,只是将它们附加到表单中的每个地址项。
是否可以仅定义特定于表单的验证组?
我使用的是Doctrine和Symfony 2.3.6。
答案 0 :(得分:1)
问题是symfony对验证组使用 OR-logic 。因此,您应用其中一个组来形成它将在两种情况下验证地址。
如果将组移动到父实体,它将无法解决问题?
/**
* @ORM\Entity()
*/
class Damage extends ...
{
/**
* @ORM\OneToOne(targetEntity="Address", cascade={"persist","remove"})
* @ORM\JoinColumn(name="responsible_address_id", referencedColumnName="id")
* @Assert\Valid(
* groups={
* "damage_responsible_address"
* })
* )
*/
private $responsibleAddress;
}
答案 1 :(得分:1)
italic 适用于一般情况,粗体适用于此问题的特定情况。
地址验证组不会查看它们的定义形式,只是将它们附加到表单中的每个地址项。
是的,您在损坏类型中的validation_group
回调为所有表单设置了validation_group
,并且当您使用cascade_validation
时,对于表单包含的所有嵌入AddressType。没有理由它应该理解你只想为负责任的地址设置它。
通常,通过回调为父表单设置验证组,并将级联验证设置为true,将使所有子表单针对此验证组进行验证。如果我们想为每个子项设置不同的验证组,我们必须在子表单类型中放置验证组回调。
您必须将验证回调放在AddressType中,以便为每个地址表调用它。当然,为了做到这一点,每个Adress实体必须知道它的所有者。
验证回调的替代方法是Group Sequence Provider。但无论如何,您仍然需要在每个地址实体中设置验证组,而不是在损坏中,因此您的地址必须仍然知道其所有者。
答案 2 :(得分:1)
我知道它已经有一段时间了,但是这里的文档可以解决symfony v3的问题:
http://symfony.com/doc/current/form/data_based_validation.html