Symfony条件形式验证

时间:2015-09-04 09:00:43

标签: validation symfony constraints conditional

我正在研究Symfony中的Form(2.6)。用户可以选择免费产品,将其发送给用户。用户必须填写一些个人信息和他的地址(义务)。如果他想指定另一个传递地址,他会检查未映射到实体的复选框,并完成传递地址。现在,我想提交表单,并且只有在用户选中此复选框时才验证交付地址字段。怎么办呢?

地址字段和传递地址字段使用映射到同一实体的相同表单类。我使用YAML文件作为我的约束。

(部分)validation.yml:

AppBundle\Entity\Address:
    properties:
        street:
          - NotBlank: { message: "Please fill in your first name." }
          - Length:
              min: 3
              max: 256
              minMessage: "Please fill in your street name."
              maxMessage: "Please fill in your street name."
        number:
          - NotBlank: { message: "Please fill in your house number." }
          - Length:
              min: 1
              max: 10
              minMessage: "Please fill in your house number."
              maxMessage: "Please fill in your house number."
        postCode:
          - NotBlank: { message: "Please fill in your postal code." }
          - Length:
              min: 2
              max: 10
              minMessage: "Please fill in your postal code."
              maxMessage: "Please fill in your postal code."
        city:
          - NotBlank: { message: "Please fill in your city." }
          - Length:
              min: 2
              max: 256
              minMessage: "Please fill in your city."
              maxMessage: "Please fill in your city."
          - Type:
              type: alpha
              message: "Please fill in your city."
        country:
          - NotBlank: { message: "Please select your country." }
          - Country: ~

AppBundle\Entity\Product:
    properties:
      product:
        - NotBlank: { message: "Please select your product." }
        - Type:
            type: integer
            message: "Please select your product."
      contact:
          - Type:
              type: AppBundle\Entity\Contact
          - Valid: ~
      deliveryAddress:
          - Type:
              type: AppBundle\Entity\Address
          - Valid: ~

产品表格类:

    <?php

class ProductFormType extends AbstractType
{

    /**
     *
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Product'
        ));
    }

    /**
     * Returns the name of this type.
     *
     * @return string The name of this type
     */
    public function getName()
    {
        return 'product';
    }


    /**
     *
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('contact', new ContactFormType()); //CONTACTFORMTYPE also has an AddressFormType for the Address Fields

        $builder->add('differentDeliveryAddress', 'checkbox', array( //delivery address is only specific for this Form
            'label'     => 'Different Shipping Address',
            'required'  => false,
            'mapped'    => false
        ));
        $builder->add('deliveryAddress', new AddressFormType());

        //specific

        $builder->add('product', 'choice', array(
            'choices' => array('a'=>'product x','b' => 'product y'),
            'required' => true,
            'invalid_message' => 'This field is required',
            'label' => 'Your Free Product',
        ));

        $builder->add('submit', 'button', array('label' => 'Submit'));
    }
}

最后是我的控制器中的getProductFormAction

   public function getProductFormAction(Request $request)
{

    $product = new Product();
    $form    = $this->get('form.factory')->create(new ProductFormType($product);

    $form->handleRequest($request);

    if($form->isValid()){
        return new Response('Success'); //just to test
    }

    return $this->render(
        'productForm.html.twig',
        array(
            'pageTitle'   => 'Test',
            'form'        => $form->createView()
        )
    );
}

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:7)

这可以通过小组相对容易地实现。

首先,将组添加到您希望在特定场合(您的投递地址)字段中验证的字段。

street:
      - NotBlank: 
          message: "Please fill in your first name."
          groups: [delivery]
      - Length:
          min: 3
          max: 256
          minMessage: "Please fill in your street name."
          maxMessage: "Please fill in your street name."
          groups: [delivery]

现在这些验证都在特定的组中,除非明确告知,否则不会对它们进行验证。

现在,我们让表单确定何时验证该组。

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'validation_groups' => function (FormInterface $form) {
            $data = $form->getData();

            if ($data->differentDeliveryAddress()) {
                return array('Default', 'delivery');
            }

            return array('Default');
        },
    ));
}

此处表单始终会验证&#39;默认&#39;组(所有未设置任何组的验证),并且还将验证&#39;交付&#39;设置differentDeliveryAddress时的组。

希望这有帮助

答案 1 :(得分:0)

Symfony文档中还有很多关于动态表单和实体/表单验证组的材料,它们应该指向正确的方向; e.g:

这个用例似乎在SO上出现了很多。我建议快速搜索一下,看看你是否可以发现类似的问题。

希望这会有所帮助:)