Symfony嵌入式表格条件验证

时间:2014-10-24 18:42:32

标签: php forms validation symfony

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

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

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

如果billingAddress复选框已启用,我在sameAsShipping表单上“禁用”验证时遇到问题。我无法在AddressType表单中进行条件验证,因为始终需要对shippingAddress表单强制执行。

2 个答案:

答案 0 :(得分:0)

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

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

<?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]);

答案 1 :(得分:0)

创建表单模型(我几乎在每个表单中使用它,但此处的代码未经过测试):

/**
 * @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条件:如果不是发货(地址)与发货(地址)相同,则需要结算地址。

在我看来,这一切都是明确的代码。