在 Symfony 5 中验证 AJAX 提交的表单

Posted

技术标签:

【中文标题】在 Symfony 5 中验证 AJAX 提交的表单【英文标题】:Validation of AJAX submitted forms in Symfony 5 【发布时间】:2021-02-19 04:09:36 【问题描述】:

我正在 Symfony 5.1 中构建一个 Address 表单。

它是在具有一些必填字段的AddressType 类中创建的。

$builder
        ->add('name', TextType::class, [
            'required' => false,
            'label'  => 'address.name',
            'help' => 'address.name_help',
            'attr' => [
                'placeholder' => 'address.name_ph',
            ]
        ])
        ->add('company', TextType::class, [
            'required' => false,
            'label'  => 'address.company',
            'attr' => [
                'placeholder' => 'address.company_ph',
            ]
        ])
        ->add('first_line', TextType::class, [
            'label'  => 'address.first_line',
            'attr' => [
                'placeholder' => 'address.first_line_ph',
            ]
        ])
        ->add('second_line', TextType::class, [
            'required' => false,
            'label'  => 'address.second_line',
            'attr' => [
                'placeholder' => 'address.second_line_ph',
            ]
        ])
        ->add('add_info', TextType::class, [
            'required' => false,
            'label'  => 'address.add_info',
            'help' => 'address.add_info_help',
            'attr' => [
                'placeholder' => 'address.add_info_ph',
            ]
        ])
        ->add('postcode', TextType::class, [
            'label'  => 'address.postcode',
            'attr' => [
                'placeholder' => 'address.postcode_ph',
            ]
        ])
        ->add('city', TextType::class, [
            'label'  => 'address.city',
            'attr' => [
                'placeholder' => 'address.city_ph',
            ]
        ])
        ->add('state', TextType::class, [
            'required' => false,
            'label'  => 'address.state',
            'attr' => [
                'placeholder' => 'address.state_ph',
            ]
        ])
        ->add('country', CountryType::class, [
            'label'  => 'address.country',
            'preferred_choices' => ['FR'],
            'attr' => [
                'data-toggle' => 'select',
                'placeholder' => 'address.country_ph',
            ]
        ])
        ->add('save',
                SubmitType::class,
                [
                    'label'  => $options['submit_btn_label'],
                ]
            );

如果我使用提交按钮提交此表单,一切都会按预期工作,我的表单正在处理以进行验证,如果它检测到一些错误,它们会显示在每个字段上。

这是处理表单的函数:

public function new(Request $request)

    $user = $this->getUser();
    $address = new Address();
    $address->setCreatedBy($user);
    $form = $this->createForm(AddressType::class, $address);
    //handle form
    $form->handleRequest($request);
    if ($form->isSubmitted())
        //if submit, add hidden fields
        $address = $form->getData();
        //if valid, process
        if ($form->isValid()) 
            $em = $this->getDoctrine()->getManager();
            $em->persist($address);
            $em->flush();   

            $this->addFlash(
                'success',
                'Your address was created.'
            );
            return $this->redirectToRoute('address_index');
        
     
    return $this->render('address/new.html.twig', [
        'form' => $form->createView(),
        'mode' => 'new',
    ]);          

现在,如果我通过 AJAX 请求提交此表单:

$(document).on('click', '.create-address', function() 
    console.log('submitting new address form...');
    var $form = $(this).closest('form')
    var data = $form.serializeArray();
    $.ajax(
        url : $form.attr('action'),
        type: $form.attr('method'),
        data : data
    );
);

在这种情况下,我的表单被处理以进行验证并且它通过了$form->isValid() 返回true),即使我没有提供一些必填字段。 这会导致持久化对象的过程发生,因此我得到一个 PDOException。

我的问题是: 为什么我的表单处理方式不同(尤其是在验证步骤)根据我发布数据的方式? 从处理请求的函数的角度来看,这两种方法有什么不同?

【问题讨论】:

【参考方案1】:

required option 仅将required 属性添加到标记中。这会强制浏览器提供一个值,但不会添加任何验证服务器端。您可以在 ajax 调用之前trigger validation 并仅在表单状态有效时提交。

但建议通过在表单中​​使用constraints 选项或注释目标实体来显式添加服务器端验证。详情请参考to the documentation。

【讨论】:

感谢您回答@msg。我了解必需属性和约束之间的区别。实体Address 定义有一些约束,例如不可为空。 好吧,其实我误解了约束和ORM规则的区别。 (我有针对不可空字段的 ORM 规则,我认为这对于验证来说是不够的/等效的)。谢谢 @Corentoulf 我正要问这个。但是,从 4.3 开始,它们应该是 automatically generated。 哼.. 所以这是一种奇怪的行为吧?无论如何添加约束“强制”验证。 @Corentoulf 我发现最好是明确的,所以我通常会添加它们而不依赖于该功能,所以我不能肯定地告诉你,可能是回归。你能检查你是否安装了symfony/property-info所需的依赖项吗? (我认为你应该,这只是好奇)。

以上是关于在 Symfony 5 中验证 AJAX 提交的表单的主要内容,如果未能解决你的问题,请参考以下文章

Symfony3 + Select2 AJAX - 禁用选择验证

如何在 symfony2 中提交表单 ajax?

使用 ajax 提交 symfony 3 表单

Symfony2:使用 ajax 和验证更改选择

带有 RESTful 身份验证的 Symfony2 应用程序,使用 FOSRestBundle 和 FOSUserBundle

PHP symfony 4 ajax 表单提交