Symfony嵌入式表单条件验证

3

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

$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 表单,它总是需要强制执行。
2个回答

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

1
创建一个表单模型(我在几乎每个表单中都使用它,但这里的代码没有经过测试):
/**
 * @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 条件:如果账单地址与邮寄地址不同,则需要填写账单地址。这就是我认为清晰的代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接