【问题标题】:Symfony Embedded Form Conditional ValidationSymfony 嵌入式表单条件验证
【发布时间】:2014-10-24 18:42:32
【问题描述】:

我有一个包含三个对象的表单:

$builder
    ->add('customer', new CustomerType())
    ->add('shippingAddress', new AddressType())
    ->add('billingAddress', new AddressType())
    ->add('sameAsShipping', 'checkbox', ['mapped' => false])
;

每个嵌入式表单都有自己的验证约束,并且它们可以工作。在我的主表单中,我有 cascade_validation => true 以便应用所有嵌入式表单验证约束。这也有效。

如果启用了sameAsShipping 复选框,我将无法“禁用”billingAddress 表单上的验证。我无法在 AddressType 表单中进行有条件的验证,因为它始终需要对 shippingAddress 表单强制执行。

【问题讨论】:

    标签: php forms validation symfony


    【解决方案1】:

    我已经通过使用验证组解决了同样的问题。

    首先,这很重要:使用AddressType 中的validation_groups 选项在类型中设置每个字段的每个约束 的验证组:

    <?php
    
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Component\Form\FormBuilderInterface;
    
    class AddressType extends \Symfony\Component\Form\AbstractType
    {
        function buildForm(FormBuilderInterface $builder, array $options)
        {
            $groups = $options['validation_groups'];
    
            $builder->add('firstName', 'text', ['constraints' => new Assert\NotBlank(['groups' => $groups])]);
            $builder->add('lastName', 'text', ['constraints' => new Assert\NotBlank(['groups' => $groups])]);
        }
    }
    

    然后,在父表单中将不同的验证组传递给两个字段:

    <?php
    
    $formBuilder = $this->get('form.factory')
        ->createNamedBuilder('checkout', 'form', null, [
            'cascade_validation' => true,
        ])
        ->add('billingAddress', 'address', [
            'validation_groups' => 'billingAddress'
        ])
        ->add('shippingAddress', 'address', [
            'validation_groups' => 'shippingAddress'
        ]);
    

    然后,通过查看复选框的值来确定您的验证组。

    if ($request->request->get('sameAsShipping')) {
        $checkoutValidationGroups = ['Default', 'billingAddress'];
    } else {
        $checkoutValidationGroups = ['Default', 'billingAddress', 'shippingAddress'];
    }
    

    然后,您可以使用验证组机制仅验证 billingAddressshippingAddress,或同时验证两者。

    我选择使用按钮:

    $formBuilder->add('submitButton', 'submit', ['validation_groups' => $checkoutValidationGroups]);
    

    【讨论】:

      【解决方案2】:

      创建一个表单模型(我几乎在每个表单中都使用它,但这里的代码没有经过测试):

      /**
       * @Assert\GroupSequenceProvider()
       */
      class YourForm implements GroupSequenceProviderInterface {
        /**
         * @Assert\Valid()
         */
        private $customer;
      
        /**
         * @Assert\Valid()
         */
        private $shippingAddress;
      
        /**
         * @Assert\Valid(groups={'BillingAddressRequired'})
         */
        private $billingAddress;
      
        private $billingSameAsShipping;
      
        public function getGroupSequence() {
          $groups = ['YourForm'];
      
          if(!$this->billingSameAsShipping) {
            $groups[] = 'BillingAddressRequired';
          }
      
          return $groups;
        }
      }
      

      尝试使用有意义的名称。 sameAsShipping 很难理解。阅读getGroupSequence 中的 if 条件:如果不是帐单(地址)与送货(地址)相同,则需要帐单地址。

      就是这样,我认为代码清晰。

      【讨论】:

        猜你喜欢
        • 2017-08-04
        • 2015-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多