2015-09-04 130 views
3

我正在Symfony(2.6)中的窗体上工作。用户可以选择一个免费的产品,这些产品将被运送给用户。用户必须填写一些个人信息和他的地址(义务)。如果他想指定另一个送货地址,他会检查未映射到实体的复选框,并完成送货地址。现在,我想提交表单,并且只有在用户选中此复选框后才验证投递地址字段。如何才能做到这一点?Symfony条件表单验证

地址字段和传递地址字段使用映射到相同实体的相同表单类。我为我的约束使用YAML文件。

(的一部分)validation.yml:

AppBundle\Entity\Address: 
    properties: 
     street: 
      - NotBlank: { message: "Please fill in your first name." } 
      - Length: 
       min: 3 
       max: 256 
       minMessage: "Please fill in your street name." 
       maxMessage: "Please fill in your street name." 
     number: 
      - NotBlank: { message: "Please fill in your house number." } 
      - Length: 
       min: 1 
       max: 10 
       minMessage: "Please fill in your house number." 
       maxMessage: "Please fill in your house number." 
     postCode: 
      - NotBlank: { message: "Please fill in your postal code." } 
      - Length: 
       min: 2 
       max: 10 
       minMessage: "Please fill in your postal code." 
       maxMessage: "Please fill in your postal code." 
     city: 
      - NotBlank: { message: "Please fill in your city." } 
      - Length: 
       min: 2 
       max: 256 
       minMessage: "Please fill in your city." 
       maxMessage: "Please fill in your city." 
      - Type: 
       type: alpha 
       message: "Please fill in your city." 
     country: 
      - NotBlank: { message: "Please select your country." } 
      - Country: ~ 

AppBundle\Entity\Product: 
    properties: 
     product: 
     - NotBlank: { message: "Please select your product." } 
     - Type: 
      type: integer 
      message: "Please select your product." 
     contact: 
      - Type: 
       type: AppBundle\Entity\Contact 
      - Valid: ~ 
     deliveryAddress: 
      - Type: 
       type: AppBundle\Entity\Address 
      - Valid: ~ 

产品形态类别:

<?php 

class ProductFormType extends AbstractType 
{ 

    /** 
    * 
    * @param OptionsResolverInterface $resolver 
    */ 
    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\Product' 
     )); 
    } 

    /** 
    * Returns the name of this type. 
    * 
    * @return string The name of this type 
    */ 
    public function getName() 
    { 
     return 'product'; 
    } 


    /** 
    * 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('contact', new ContactFormType()); //CONTACTFORMTYPE also has an AddressFormType for the Address Fields 

     $builder->add('differentDeliveryAddress', 'checkbox', array(//delivery address is only specific for this Form 
      'label'  => 'Different Shipping Address', 
      'required' => false, 
      'mapped' => false 
     )); 
     $builder->add('deliveryAddress', new AddressFormType()); 

     //specific 

     $builder->add('product', 'choice', array(
      'choices' => array('a'=>'product x','b' => 'product y'), 
      'required' => true, 
      'invalid_message' => 'This field is required', 
      'label' => 'Your Free Product', 
     )); 

     $builder->add('submit', 'button', array('label' => 'Submit')); 
    } 
} 

最后getProductFormAction在我的控制器

public function getProductFormAction(Request $request) 
{ 

    $product = new Product(); 
    $form = $this->get('form.factory')->create(new ProductFormType($product); 

    $form->handleRequest($request); 

    if($form->isValid()){ 
     return new Response('Success'); //just to test 
    } 

    return $this->render(
     'productForm.html.twig', 
     array(
      'pageTitle' => 'Test', 
      'form'  => $form->createView() 
     ) 
    ); 
} 

预先感谢您的帮助!

+0

可能重复[条件字段有效性依赖于其他领域(http://stackoverflow.com/questions/20471812/conditional-field-validation-that-depends-on-another-字段) –

回答

0

Symfony文档中还有很多关于动态表单和实体/表单验证组的材料,这些材料应该指向正确的方向; e.g:

该用例似乎来了很多的SO。我建议你快速搜索一下,看看你是否可以发现类似的问题。

希望这有助于:)

+0

我阅读了两章,并试图使用eventListener为我的复选框和使用验证组实现解决方案。也许我做了错误的事情,但验证器一直使用主地址类型的验证。我将使用一个经典的PHP'是复选框'检查' - 解决方案。谢谢你的帮助! –

7

这可以通过组相对容易地实现。

首先,将组添加到您只想在某些场合(您的送货地址)字段中验证的字段。

street: 
     - NotBlank: 
      message: "Please fill in your first name." 
      groups: [delivery] 
     - Length: 
      min: 3 
      max: 256 
      minMessage: "Please fill in your street name." 
      maxMessage: "Please fill in your street name." 
      groups: [delivery] 

既然这些验证是在特定的组中,除非明确告知这些验证,否则它们将不会被验证。

所以现在,我们让表单决定何时验证这个组。

public function configureOptions(OptionsResolver $resolver) 
{ 
    $resolver->setDefaults(array(
     'validation_groups' => function (FormInterface $form) { 
      $data = $form->getData(); 

      if ($data->differentDeliveryAddress()) { 
       return array('Default', 'delivery'); 
      } 

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

这里的形式将始终验证“默认”组(没有任何组的所有验证中设置),也将验证“输送”基团时differentDeliveryAddress被设置。

希望这有助于的