2015-09-04 129 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被設置。

希望這有助於的