【问题标题】:2 subforms with same Entity with different validation Symfony2具有相同实体的 2 个子表单具有不同的验证 Symfony2
【发布时间】:2015-07-12 20:11:51
【问题描述】:

在我的 Symfony2 应用程序中,我有一个表单订阅,其中包含使用相同实体地址的 2 个子表单。 我正在寻找一种解决方案,仅在未选中复选框时才验证第二种形式。由于子表单属于同一实体,因此验证约束是相同的。 Assert\Valid 实体不能带组参数,所以我不能使用这个解决方案。

订阅类型.php

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('billingAddress', new AddressType())
        ->add('shippingSame', 'checkbox', array(
                'mapped' => false,
                'data' => true,
        ))
        ->add('shippingAddress', new AddressType())
    ;       
}

Adress.php 实体

class Address
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="firstname", type="string", length=255, nullable=false)
     * @Assert\NotBlank()
     */
    private $firstname;

    /**
     * @var string
     *
     * @ORM\Column(name="line1", type="string", length=255, nullable=false)
     * @Assert\NotBlank()
     */
    private $line1;
}

Suscription.php 条目

class Subscription
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Shop\Address")
     * @ORM\JoinColumn(nullable=false)
     */
    private $billingAddress;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Shop\Address")
     * @ORM\JoinColumn(nullable=false)
     */
    private $shippingAddress;
}

所以,我只想在未选中未映射复选框的情况下验证第二个地址。

感谢您的帮助!

【问题讨论】:

    标签: forms validation symfony


    【解决方案1】:

    使用未映射字段的唯一方法是直接访问表单数据,这违背了验证的目的。要使用 symfony 的 Validator 组件,您必须映射复选框。只需将此字段添加到您的实体,您不必将其映射到 DB。

    /**
     * @var bool
     */
    private $shippingSame;
    
    /**
     * @return bool
     */
    public function isShippingSame()
    {
        return $this->shippingSame;
    }
    
    /**
     * @param bool $shippingSame
     */
    public function setShippingSame($shippingSame)
    {
        $this->shippingSame = $shippingSame;
    }
    

    然后您可以在@Assert\Callback() 中轻松访问它:

    public function validateShipping(ExecutionContextInterface $context)
    {
        if ($this->isShippingSame()) {
            $isValid = ... ; // do the validation
            if (!$isValid) {
                $context
                    ->buildViolation('Shipping address is not valid!')
                    ->atPath('shippingAddress')
                    ->addViolation();
            }   
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用表格Validation Groups features

      您需要一些高级逻辑来确定验证组(基于提交的数据),您可以将 validation_groups 选项设置为数组回调,如下所示:

      订阅类型.php

      use Symfony\Component\Form\FormInterface;
      use Symfony\Component\OptionsResolver\OptionsResolver;
      
      // before the 2.7 version this method is called setDefaultOptions
      public function configureOptions(OptionsResolver $resolver)
      {
          $resolver->setDefaults(array(
              'validation_groups' => function (FormInterface $form) {
                  $data = $form->getData();
      
                  if (true == $data->shippingSame) {
                      return array('validate_only_billing_address');
                  }
      
                  return array('validate_shipping_billing_address');
              },
          ));
      }
      

      并在您的实体中添加正确的验证组注释。

      希望对您有所帮助。如果您需要更多建议,请告诉我。

      【讨论】:

      • 感谢您的解决方案,但由于 2 个子表单的实体相同,因此验证组将相同(因为定义的 Entity 类中有注释),所以我们不能使用 groups_validation我想。
      • 嗨@Nbalive16 与文档You can change the Groups based on the Submitted Data 一致,我经常使用此功能。顺便说一句,回调方法也是一种解决方案。
      • 是的,我们可以根据数据改变分组,但是分组是通过注解定义到实体类文件中的。由于我的实体(以及我的字段)对于 2 个子表单是相同的,因此无法定义和使用 2 个不同的组。无论如何,非常感谢您的帮助;)
      【解决方案3】:
      $resolver->setDefaults(array(
          'validation_groups' => function (FormInterface $form) {
      
              if (true == $form->get('shippingSame')->getData()) {
                  return array('validate_only_billing_address');
              }
      
              return array('validate_shipping_billing_address');
          },
      ));
      

      我只更改了 get() 属性。 也许只是版本差异(老实说我没有调查) 实际上我在最后一个 v2.7.1 上运行。

      希望这可以帮助某人

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-09
        相关资源
        最近更新 更多