使用Symfony Form处理AJAX请求时无法验证表单的问题
问题:jQuery AJAX提交表单时,Symfony的
$form->isSubmitted()不生效 通过jQuery AJAX提交创建请求时,无法使用$form->isSubmitted() && $form->isValid()处理和验证表单,因为$form->isSubmitted()始终返回false。
相关代码
表单构建与视图渲染(PHP)
public function index(Request $request, EntityManagerInterface $entityManager): Response { $category = new Category(); $form = $this->createForm(CategoryFormType::class, $category); $form->handleRequest($request); $list = $entityManager->getRepository(Category::class)->listCategory(); return $this->render('admin/index/category.html.twig', [ 'categoryForm' => $form->createView(), 'list' => $list ]); }
AJAX请求代码(JavaScript)
$(document).ready(function(){ $("#category-add").submit(function(e){ e.preventDefault(); var form = $(this); $.ajax({ type: "PUT", url: '/api/admin/category', data: form.serialize(), dataType: 'x-www-form-urlencoded', success: function(data) { console.log(data); } }); }); });
表单请求处理(PHP)
public function add(Request $request, EntityManagerInterface $entityManager): Response { $category = new Category(); $form = $this->createForm(CategoryFormType::class, $category); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $category->setCategoryName($form->get('categoryName')->getData()); $entityManager->persist($category); $entityManager->flush(); return new response('true'); } return new response('false'); }
Twig模板代码
<form id="category-add"> <input type="hidden" name="csrf_token" value="{{ csrf_token('add-category') }}" /> <input type="text" name="categoryName" placeholder="Nazwa kategorii" class="w-full bg-black border border-grey-one rounded px-4 py-2 focus:outline-none text-sm text-white-two mb-4" /> <button class="w-full uppercase bg-green-three px-6 py-3 rounded-md text-white font-semibold tracking-wide text-xs focus:outline-none" type="submit">Dodaj</button> </form>
问题原因及解决方案
1. 表单字段缺少Symfony命名空间前缀
Symfony表单默认会为字段添加表单名称作为前缀(例如category_form[categoryName]),但你的Twig模板直接使用categoryName作为字段名,导致handleRequest无法识别这是表单提交的字段。
解决方法:
- 推荐方案:使用Symfony表单组件原生渲染字段
{{ form_start(categoryForm, { 'id': 'category-add' }) }} {{ form_widget(categoryForm.categoryName, { 'attr': { 'placeholder': 'Nazwa kategorii', 'class': 'w-full bg-black border border-grey-one rounded px-4 py-2 focus:outline-none text-sm text-white-two mb-4' } }) }} {{ form_widget(categoryForm._token) }} <button class="w-full uppercase bg-green-three px-6 py-3 rounded-md text-white font-semibold tracking-wide text-xs focus:outline-none" type="submit">Dodaj</button> {{ form_end(categoryForm) }}
此方式会自动添加表单前缀,且CSRF令牌与表单自动关联。
- 手动方案:为字段添加前缀
若坚持手动编写HTML,需给字段加上表单名称前缀(默认表单名为category_form),同时使用表单原生CSRF令牌:
<form id="category-add"> <input type="hidden" name="category_form[_token]" value="{{ categoryForm._token.vars.value }}" /> <input type="text" name="category_form[categoryName]" placeholder="Nazwa kategorii" class="w-full bg-black border border-grey-one rounded px-4 py-2 focus:outline-none text-sm text-white-two mb-4" /> <button class="w-full uppercase bg-green-three px-6 py-3 rounded-md text-white font-semibold tracking-wide text-xs focus:outline-none" type="submit">Dodaj</button> </form>
2. AJAX请求配置错误
dataType是预期的响应类型,而非发送数据的类型,应将其改为实际响应类型(如'json'),contentType设置为application/x-www-form-urlencoded(jQuery默认值可省略)。- 请求方法适配:Symfony表单默认处理POST请求,若使用PUT,需在创建表单时指定方法:
$form = $this->createForm(CategoryFormType::class, $category, [ 'method' => 'PUT', ]);
或在AJAX中使用POST请求,同时在表单添加_method隐藏字段:
<input type="hidden" name="_method" value="PUT">
3. CSRF令牌不匹配
你手动生成的CSRF令牌与表单令牌无关联,会导致验证失败,间接影响isSubmitted()判断。使用表单原生令牌即可解决该问题,如上述方案所示。
4. 验证请求数据
在add方法中,可通过var_dump($request->request->all())查看提交的数据,确认是否包含带前缀的表单字段,排查请求是否正确传递。
内容的提问来源于stack exchange,提问作者Zgedek IKS DE
相关产品推荐
相关产品推荐

