如何从Symfony控制器传递数组到JavaScript,适配typeahead自动补全需求
Symfony 对接 Typeahead 自动补全组件实现方案
有两种常用实现方案,可根据业务场景选择:
方案1:页面渲染时一次性注入数据(适合数据量小的场景)
无需额外异步请求,页面加载时直接把全量数据注入到前端:
- 修改控制器,渲染模板时传入序列化后的团队数据
/** * @Route(name="teams_page", path="/your-page-path") */ public function page() { $em = $this->getDoctrine()->getManager(); $teams = $em->getRepository(Teams::class)->findAll(); $data = []; foreach($teams as $team){ $data[] = $team->getName(); } return $this->render('your_template.html.twig', [ 'teamData' => json_encode($data) ]); }
- 在Twig模板中注入数据到JS变量
<script> const teamData = {{ teamData|raw }}; </script>
- 修改Typeahead配置,移除冗余的ajax配置
$.typeahead({ input: '[data-autocomplete="team"]', minLength: 1, order: "asc", offset: true, hint: true, source: { items: { data: teamData } }, });
方案2:异步动态请求(适合数据量大的场景)
用户输入时动态发起请求匹配结果,现有代码需要做以下修正:
前端JS修正点:
- 移除
data配置项,避免和ajax逻辑冲突 - ajax的
data参数使用函数动态获取当前输入值,避免页面加载时就取到固定的空值 - 推荐使用Twig的
path函数生成路由,避免硬编码路径错误
修正后代码:
$.typeahead({ input: '[data-autocomplete="team"]', minLength: 1, order: "asc", offset: true, hint: true, source: { items: { ajax: { type: "POST", url: "{{ path('teams') }}", data: function () { return { myKey: $('[data-autocomplete="team"]').val(), _token: "{{ csrf_token('autocomplete_team') }}" } } } } }, });
控制器修正点:
- 路由指定允许POST请求
- 接收前端传入的关键词做模糊查询,不需要每次返回全量数据
- 校验CSRF令牌保证请求安全
- JsonResponse不需要传第四个参数,默认序列化即可
修正后代码:
/** * @Route(name="teams", path="/teams", methods={"POST"}) */ public function sendTeams(Request $request) { // 校验CSRF令牌 if (!$this->isCsrfTokenValid('autocomplete_team', $request->request->get('_token'))) { return new JsonResponse([], 403); } $keyword = $request->request->get('myKey', ''); $em = $this->getDoctrine()->getManager(); // 模糊查询匹配名称的团队 $teams = $em->getRepository(Teams::class)->createQueryBuilder('t') ->where('t.name LIKE :keyword') ->setParameter('keyword', '%'.$keyword.'%') ->getQuery() ->getResult(); $data = []; foreach($teams as $team){ $data[] = $team->getName(); } return new JsonResponse($data); }
内容的提问来源于stack exchange,提问作者user3461461
相关产品推荐
相关产品推荐

