2017-08-16 15 views
5

我正嘗試使用付款和送貨地址創建地址表單。當收件人地址上的複選框被選中時,我想跳過該地址上的表單驗證。如果在Symfony中選中複選框,請關閉窗體類型的驗證

我已經使用切換選項創建了下面的表單類型,該選項將顯示和處理複選框,但是即使選中該表單也仍然有效。

Symfony有documentation on how to implement such a form,即使我幾乎有完全相同的代碼,檢查時驗證沒有關閉。我沒有使用驗證組,所以我只是禁用默認組來禁用對實體的驗證。

AddressType構建Address類的表單(其對NotBlankCallback等某些字段具有註釋限制)。

class AddressType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     if ($options["toggle"]) { 
      $builder->add("toggle", CheckboxType::class, [ 
       "mapped" => false, 
       "required" => false, 
       "label" => $options["toggle"] 
      ]); 
     } 

     $builder 
      ->add("name", TextType::class, [ 
       "required" => !$options["toggle"] 
      ]) 
      ->add("address", TextType::class, [ 
       "required" => !$options["toggle"] 
      ]) 
      ->add("zipcode", TextType::class, [ 
       "label" => "Postcode", 
       "required" => !$options["toggle"] 
      ]) 
      ->add("city", TextType::class, [ 
       "required" => !$options["toggle"] 
      ]) 
      ->add("countryCode", ChoiceType::class, [ 
       "choices" => Address::COUNTRY_CODES 
      ]); 
    } 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults([ 
      "toggle" => false, 
      "data_class" => Address::class, 
      "validation_groups" => function(FormInterface $form) { 
       if ($form->has("toggle") && $form->get("toggle")->getData() === true) { 
        return []; 
       } 

       return ["Default"]; 
      } 
     ]); 

     $resolver->setAllowedTypes("toggle", ["bool", "string"]); 
    } 
} 

我使用這樣的類型:

$addressForm = $this 
    ->createFormBuilder([ 
     "paymentAddress" => $paymentAddress, 
     "shippingAddress" => $shippingAddress 
    ]) 
    ->add("paymentAddress", AddressType::class, [ 
     "label" => false 
    ]) 
    ->add("shippingAddress", AddressType::class, [ 
     "label" => false, 
     "toggle" => "Use payment address" 
    ]) 
    ->add("submit", SubmitType::class, [ 
    ]) 
    ->getForm(); 

我已經打算在這幾個小時,但現在我不能推斷出爲什麼驗證不被關閉,我我不願意在這個小小的細節上搞個形式。

爲什麼驗證AddressType未被configureOptions中的閉包關閉?如果這不是它的工作原理,那麼以更簡潔的方式完成部分關閉驗證的更好的解決方案是什麼?

編輯:即使在默認值中設置"validation_groups" => false,在構建器中創建的子元素或表單的使用中,仍然會進行驗證。它不需要關閉。每個在線資源,包括Symfony自己的資源狀態,它應該雖然工作...

回答

2

[...]所以我只是禁用默認組來禁用對實體的驗證。

假設Address性能&約束是這樣的:

/** 
* @Assert\NotBlank() 
*/ 
private $name; 

// etc. 

的「驗證」假定這些特性將與Default組進行評估,因爲他始終認爲空validation_groups(如return [];)爲['Default'] (因此在檢查時驗證不關閉):

https://symfony.com/doc/current/validation/groups.html: 如果未指定組,則將應用屬於組Default的所有約束。

一個解決方案來實現部分在一個整潔的方式關閉驗證

如果有很多方法可以實現,但我告訴你他們兩個:

  1. 如果沒有data_class設置爲根形式,那麼只有Form組可用於驗證此級別:

    $addressForm = $this 
        ->createFormBuilder([...], [ 
         'validation_groups' => 'Form', // <--- set 
        ]) 
    

    接下來,在configureOptions方法,設置Address組作爲默認和Form組如果「開關」被選中,還增加了對級聯驗證Valid()約束:

    public function configureOptions(OptionsResolver $resolver) 
    { 
        $resolver->setDefaults([ 
         // ... 
         "validation_groups" => function(FormInterface $form) { 
          if ($form->has("toggle") && $form->get("toggle")->getData() === true) { 
           return ['Form']; // <--- set 
          } 
    
          return ['Address']; // <--- set 
         }, 
         'constraints' => [new Assert\Valid()], // <--- set 
        ]); 
    } 
    

    這意味着,與切換關閉提交:FormAddress組適用於地址字段,否則,只應用Form組。

  2. 「所需」(另一種方法)在Address類添加組的所有約束,它避免了與Default組驗證這些屬性:

    /** 
    * @Assert\NotBlank(groups={"Required"}) // <--- set 
    */ 
    private $name; 
    
    // etc. 
    

    接着,在configureOptions方法設定Required作爲默認組和Default如果撥動檢查:

    public function configureOptions(OptionsResolver $resolver) 
    { 
        $resolver->setDefaults([ 
         // ... 
         "validation_groups" => function(FormInterface $form) { 
          if ($form->has("toggle") && $form->get("toggle")->getData() === true) { 
           return ['Default']; // <--- set 
          } 
    
          return ['Required']; // <--- set 
         }, 
         'constraints' => [new Assert\Valid()], // <--- set 
        ]); 
    } 
    

    在這種情況下,與切換關閉提交:DefaultRequired組應用於地址字段,否則只有Default組,因此跳過了必填字段。

  3. 包含來自根對象斷開連接對象

嵌套形式可通過約束選項設置爲new Valid()進行驗證。

+1

感謝您的詳細解答。我已經嘗試向所有約束添加組,並默認從validation_groups閉包中返回這些組。我缺少的是有效約束。我沒有想到添加的字段會成爲AddressType的子節點,因此需要約束。 – Villermen

相關問題