Symfony 5.4 base.twig导航栏搜索表单提交无结果解决方法
问题核心原因
你遇到的提交失效问题是以下几个点叠加导致的:
- 用
{{ render(controller()) }}子请求渲染表单时,没有给表单显式指定提交地址,Form组件会自动把当前浏览的页面URL作为表单action,提交请求根本没发到你写的app_search路由,而是发到了当前页(比如首页、列表页),这些页面对应的控制器没有处理搜索表单的逻辑,自然不会返回结果。 - 子请求本身会生成独立的Request实例,即便请求发到了正确路由,嵌套渲染时也容易出现表单提交状态识别异常的问题。
- 额外的代码bug:结果模板里
{% for Gry in Gry %}循环变量和结果集重名,即便拿到数据也会渲染异常。
可直接落地的实现方案
方案1:修正原有Form组件逻辑(保留FormBuilder用法)
1. 给表单显式绑定提交路由和请求方法
修改控制器中创建表单的代码,固定表单提交地址,避免子请求自动获取当前URL的问题,搜索场景推荐用GET方法,避免重复提交弹窗、支持搜索结果分享:
#[Route('/search/SBresult', name: 'app_search')] public function searchBar(Request $request, EntityManagerInterface $entityManager): Response { // 移除方法参数里默认的$Nazwa定义,完全从请求取数据 $form = $this->createFormBuilder([], [ 'action' => $this->generateUrl('app_search'), // 固定提交到搜索路由 'method' => 'GET', ]) ->add('Nazwa', TextType::class, [ 'required' => false, 'label' => 'wpisz nazwę gry', 'label_attr'=> ['class'=>'text-white ps-3'], 'attr' => ['class'=>'form-control form-control-lg'] ]) ->getForm(); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $Nazwa = $form->get('Nazwa')->getData(); $Gry = $entityManager->getRepository(Gra::class)->findGra($Nazwa); return $this->render('search/SBresult.html.twig', ['Gry' => $Gry]); } // 这个模板只返回表单片段,供base模板嵌入用,不要加全局html/body标签 return $this->render('search/searchBar.html.twig', ['form' => $form->createView()]); }
2. 修正模板代码
- 嵌入用的表单片段模板
search/searchBar.html.twig,只保留表单渲染逻辑,不要套完整页面结构:
{{ form_start(form, {attr: {class: 'd-flex'}}) }} {{ form_label(form.Nazwa) }} {{ form_widget(form.Nazwa) }} <button type="submit" class="btn btn-primary ms-2 align-self-center">搜索</button> {{ form_rest(form) }} {{ form_end(form) }}
- 结果页模板
search/SBresult.html.twig修正循环变量重名问题,且必须继承base模板:
{% extends 'base.html.twig' %} {% block body %} <h1>搜索结果</h1> {% if Gry is empty %} <div class="alert alert-info">没有找到匹配的游戏</div> {% else %} <div class="game-list"> {# 注意循环单个变量不要和结果集重名 #} {% for gra in Gry %} <div class="game-item"> {# 这里替换成你自己的游戏实体字段输出逻辑 #} <h3>{{ gra.nazwa }}</h3> </div> {% endfor %} </div> {% endif %} {% endblock %}
3. base模板中的渲染代码保持不变即可
{{ render(controller('App\\Controller\\SearchController::searchBar')) }}
方案2:静态表单实现(更简单稳定,无嵌套请求问题)
导航栏的单字段搜索完全不需要走子请求+FormBuilder渲染,直接写原生表单性能更高,完全规避子请求的所有坑,推荐使用:
1. 简化控制器代码
#[Route('/search/SBresult', name: 'app_search')] public function searchBar(Request $request, EntityManagerInterface $entityManager): Response { $keyword = trim($request->query->get('Nazwa', '')); $gry = []; if ($keyword) { $gry = $entityManager->getRepository(Gra::class)->findGra($keyword); } return $this->render('search/SBresult.html.twig', [ 'Gry' => $gry, 'keyword' => $keyword ]); }
2. 直接在base.twig.html导航栏对应位置写表单,删掉原来的render调用
<form action="{{ path('app_search') }}" method="get" class="d-flex"> <label for="game-search" class="text-white ps-3 align-self-center">wpisz nazwę gry</label> <input type="text" id="game-search" name="Nazwa" class="form-control form-control-lg ms-2" value="{{ app.request.query.get('Nazwa', '') }}" placeholder="输入游戏名称" > <button type="submit" class="btn btn-primary ms-2">搜索</button> </form>
3. 结果页模板和方案1的写法一致即可,注意修正循环变量重名问题。
内容的提问来源于stack exchange,提问作者Magdalena Wójcik
相关产品推荐
相关产品推荐

