Symfony 3.3.6中基于jQuery自动补全实现双搜索栏功能求助
嘿,我来帮你一步步搞定这个需求!在Symfony 3.3.6里实现带自动补全的双搜索栏(工种+城市),还要展示对应工匠,其实分后端接口开发、前端交互实现、样式贴近参考网站这三块来做就清晰了,咱们一个个来拆解:
一、Symfony后端:提供自动补全与搜索接口
首先得确保你已经有对应的实体(比如Craftsman工匠、JobType工种、City城市),接下来创建控制器和Repository方法来处理AJAX请求:
1. 创建搜索控制器
// src/AppBundle/Controller/SearchController.php namespace AppBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; use AppBundle\Entity\JobType; use AppBundle\Entity\City; use AppBundle\Entity\Craftsman; class SearchController extends Controller { // 工种自动补全接口 public function jobTypeAutocompleteAction(Request $request) { $query = $request->query->get('term', ''); $em = $this->getDoctrine()->getManager(); // 调用Repository的模糊查询方法 $jobTypes = $em->getRepository(JobType::class)->findByTerm($query); $results = []; foreach ($jobTypes as $jobType) { $results[] = [ 'id' => $jobType->getId(), 'label' => $jobType->getName(), 'value' => $jobType->getName() ]; } return new JsonResponse($results); } // 城市自动补全接口 public function cityAutocompleteAction(Request $request) { $query = $request->query->get('term', ''); $em = $this->getDoctrine()->getManager(); $cities = $em->getRepository(City::class)->findByTerm($query); $results = []; foreach ($cities as $city) { $results[] = [ 'id' => $city->getId(), 'label' => $city->getName() . ' (' . $city->getZipCode() . ')', 'value' => $city->getName() ]; } return new JsonResponse($results); } // 根据工种+城市查询工匠列表 public function searchCraftsmenAction(Request $request) { $jobTypeId = $request->query->get('job_type_id'); $cityId = $request->query->get('city_id'); $em = $this->getDoctrine()->getManager(); $craftsmen = $em->getRepository(Craftsman::class)->findByJobTypeAndCity($jobTypeId, $cityId); return $this->render('search/craftsmen_list.html.twig', [ 'craftsmen' => $craftsmen ]); } }
2. 给Repository添加查询方法
比如JobTypeRepository:
// src/AppBundle/Repository/JobTypeRepository.php namespace AppBundle\Repository; use AppBundle\Entity\JobType; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Common\Persistence\ManagerRegistry; class JobTypeRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, JobType::class); } public function findByTerm($term) { return $this->createQueryBuilder('j') ->where('j.name LIKE :term') ->setParameter('term', '%' . $term . '%') ->orderBy('j.name', 'ASC') ->setMaxResults(10) // 限制返回数量,避免太多结果 ->getQuery() ->getResult(); } }
CityRepository的findByTerm方法和上面类似,CraftsmanRepository的findByJobTypeAndCity则根据实体关联关系编写查询(比如工匠关联工种和城市)。
3. 配置路由
在app/config/routing.yml中添加:
job_type_autocomplete: path: /search/job-type-autocomplete defaults: { _controller: AppBundle:Search:jobTypeAutocomplete } city_autocomplete: path: /search/city-autocomplete defaults: { _controller: AppBundle:Search:cityAutocomplete } search_craftsmen: path: /search/craftsmen defaults: { _controller: AppBundle:Search:searchCraftsmen }
二、前端:用jQuery UI Autocomplete实现交互
首先要引入jQuery和jQuery UI的资源(可以用CDN或本地文件),然后编写页面模板和JS逻辑:
1. 搜索页面模板
创建search/index.html.twig:
{% extends 'base.html.twig' %} {% block stylesheets %} {{ parent() }} <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> <!-- 自定义样式放在下面,后面会讲怎么贴近参考网站 --> {% endblock %} {% block body %} <div class="search-container"> <h1>Trouver un artisan</h1> <div class="search-fields"> <div class="field-group"> <label for="job-type">Métier</label> <input type="text" id="job-type" placeholder="Ex: Plombier, Électricien"> <input type="hidden" id="job-type-id"> <!-- 存选中的工种ID --> </div> <div class="field-group"> <label for="city">Ville</label> <input type="text" id="city" placeholder="Ex: Paris, Lyon"> <input type="hidden" id="city-id"> <!-- 存选中的城市ID --> </div> <button id="search-btn">Rechercher</button> </div> <div id="craftsmen-results"></div> </div> {% endblock %} {% block javascripts %} {{ parent() }} <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script> <script> $(document).ready(function() { // 工种自动补全 $('#job-type').autocomplete({ source: '{{ path('job_type_autocomplete') }}', minLength: 2, // 输入至少2个字符才触发 select: function(event, ui) { $('#job-type-id').val(ui.item.id); // 选中后把ID存到隐藏域 } }); // 城市自动补全 $('#city').autocomplete({ source: '{{ path('city_autocomplete') }}', minLength: 2, select: function(event, ui) { $('#city-id').val(ui.item.id); } }); // 搜索按钮点击事件 $('#search-btn').click(function() { var jobTypeId = $('#job-type-id').val(); var cityId = $('#city-id').val(); if (!jobTypeId || !cityId) { alert('Veuillez sélectionner un métier et une ville'); return; } // AJAX请求获取工匠列表 $.ajax({ url: '{{ path('search_craftsmen') }}', data: { job_type_id: jobTypeId, city_id: cityId }, success: function(data) { $('#craftsmen-results').html(data); }, error: function() { $('#craftsmen-results').html('<p>Erreur lors de la recherche</p>'); } }); }); // 可选:当两个字段都选好时自动触发搜索 $('#job-type-id, #city-id').change(function() { var jobTypeId = $('#job-type-id').val(); var cityId = $('#city-id').val(); if (jobTypeId && cityId) { $('#search-btn').click(); } }); }); </script> {% endblock %}
2. 工匠列表模板
创建search/craftsmen_list.html.twig:
{% if craftsmen|length > 0 %} <h2>Résultats de la recherche</h2> {% for craftsman in craftsmen %} <div class="craftsman-card"> <h3>{{ craftsman.getName() }}</h3> <div class="craftsman-info"> <p>{{ craftsman.getAddress() }}</p> <p>{{ craftsman.getPhone() }}</p> <p>Métier: {{ craftsman.getJobType().getName() }}</p> </div> </div> {% endfor %} {% else %} <p>Aucun artisan trouvé pour ce métier et cette ville.</p> {% endif %}
三、样式调整:贴近参考网站风格
参考目标网站的设计,给页面添加自定义样式,把下面的代码放到search/index.html.twig的{% block stylesheets %}里:
<style> .search-container { max-width: 900px; margin: 3rem auto; padding: 0 1.5rem; } .search-fields { display: flex; gap: 1.2rem; margin: 2.5rem 0; flex-wrap: wrap; align-items: flex-end; } .field-group { flex: 1; min-width: 220px; } .field-group label { display: block; margin-bottom: 0.6rem; font-weight: 600; color: #333; } .field-group input[type="text"] { width: 100%; padding: 1rem; border: 2px solid #e0e0e0; border-radius: 4px; font-size: 1.1rem; transition: border-color 0.2s; } .field-group input[type="text"]:focus { border-color: #ff6600; outline: none; } #search-btn { padding: 1rem 2.5rem; background-color: #ff6600; color: white; border: none; border-radius: 4px; font-size: 1.1rem; font-weight: 600; cursor: pointer; transition: background-color 0.2s; } #search-btn:hover { background-color: #e55a00; } .craftsman-card { border: 1px solid #eee; border-radius: 8px; padding: 1.8rem; margin-bottom: 1.2rem; background-color: white; box-shadow: 0 2px 6px rgba(0,0,0,0.05); transition: box-shadow 0.2s; } .craftsman-card:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.1); } .craftsman-card h3 { margin-top: 0; color: #ff6600; font-size: 1.3rem; } .craftsman-info { display: flex; gap: 1.5rem; margin-top: 0.8rem; flex-wrap: wrap; color: #555; } .craftsman-info p { margin: 0; display: flex; align-items: center; gap: 0.3rem; } </style>
这样一套下来,就能实现你想要的功能啦!如果还有细节需要调整,比如自动补全的样式、工匠卡片的内容,都可以根据需求再修改。
内容的提问来源于stack exchange,提问作者mouss
相关产品推荐
相关产品推荐

