2015-07-12 58 views
2

在我的Symfony2应用程序中,我有一个具有2个子表单的订阅使用相同的实体地址。 我正在寻找解决方案来验证第二个窗体只有当复选框未选中。由于子表单属于同一实体,所以验证约束是相同的。断言\有效的实体cannont采取组参数,这样我就可以“T使用此解决方案。2具有不同验证的相同实体的子表单Symfony2

SubscriptionType.php

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('billingAddress', new AddressType()) 
     ->add('shippingSame', 'checkbox', array(
       'mapped' => false, 
       'data' => true, 
     )) 
     ->add('shippingAddress', new AddressType()) 
    ;  
} 

Adress.php实体

class Address 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="firstname", type="string", length=255, nullable=false) 
    * @Assert\NotBlank() 
    */ 
    private $firstname; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="line1", type="string", length=255, nullable=false) 
    * @Assert\NotBlank() 
    */ 
    private $line1; 
} 

Suscription.php Entiry

class Subscription 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Shop\Address") 
    * @ORM\JoinColumn(nullable=false) 
    */ 
    private $billingAddress; 

    /** 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Shop\Address") 
    * @ORM\JoinColumn(nullable=false) 
    */ 
    private $shippingAddress; 
} 

所以,我想验证第二个地址只有当未映射的复选框未选中。

感谢您的帮助!

回答

0

处理未映射字段的唯一方法是直接访问表单数据,这就违背了验证的目的。要使用symfony的Validator组件,您必须使复选框映射。只需将此字段添加到您的实体,您不必将其映射到数据库。

/** 
* @var bool 
*/ 
private $shippingSame; 

/** 
* @return bool 
*/ 
public function isShippingSame() 
{ 
    return $this->shippingSame; 
} 

/** 
* @param bool $shippingSame 
*/ 
public function setShippingSame($shippingSame) 
{ 
    $this->shippingSame = $shippingSame; 
} 

然后你就可以轻松地访问它在@Assert\Callback()

public function validateShipping(ExecutionContextInterface $context) 
{ 
    if ($this->isShippingSame()) { 
     $isValid = ... ; // do the validation 
     if (!$isValid) { 
      $context 
       ->buildViolation('Shipping address is not valid!') 
       ->atPath('shippingAddress') 
       ->addViolation(); 
     } 
    } 
} 
0

您可以使用表格Validation Groups features

你需要一些先进的逻辑来确定确认团组(根据提交的数据),可以将validation_groups选项设置为一个数组回调如下:

SubscriptionType.php

use Symfony\Component\Form\FormInterface; 
use Symfony\Component\OptionsResolver\OptionsResolver; 

// before the 2.7 version this method is called setDefaultOptions 
public function configureOptions(OptionsResolver $resolver) 
{ 
    $resolver->setDefaults(array(
     'validation_groups' => function (FormInterface $form) { 
      $data = $form->getData(); 

      if (true == $data->shippingSame) { 
       return array('validate_only_billing_address'); 
      } 

      return array('validate_shipping_billing_address'); 
     }, 
    )); 
} 

并添加您实体中的正确验证组注释。

希望得到这个帮助。让我知道你是否需要更多建议。

+0

感谢您的解决方案,但由于实体是同为2子窗体时,确认团组将是相同的(因为定义在实体类注释),所以我们可以我认为不要使用groups_validation。 – Nbalive16

+0

Hi @ Nbalive16与文档[您可以根据提交的数据更改群组](http://symfony.com/doc/current/book/forms.html#validation-groups)手风琴,我经常使用此功能。顺便说一句,回调方法也是一个解决方案。 – Matteo

+1

是的,我们可以根据数据更改组,但组是使用注释定义到实体类文件中的。由于我的实体(以及我的领域)对于2个子表单是相同的,因此定义和使用2个不同的组是不可能的。无论如何,非常感谢您的帮助;) – Nbalive16

0
$resolver->setDefaults(array(
    'validation_groups' => function (FormInterface $form) { 

     if (true == $form->get('shippingSame')->getData()) { 
      return array('validate_only_billing_address'); 
     } 

     return array('validate_shipping_billing_address'); 
    }, 
)); 

我改变了get()属性。 也许只是一个版本差异(老实说,我没有调查) 实际上我运行在最后的v2.7.1上。

希望这可以帮助别人