使用 Ajax 的 Symfony 动态搜索字段

Symfony dynamic search field using Ajax

我想在 Symfony 中使用 Ajax 实现动态搜索。我的数据库中有一个名为 Session 的实体和一个 table。 我想从 table 加载数据并将它们显示在模板中。然后,使用文本字段,我可以简单地写下我要搜索的内容,它会动态显示。

我可以从数据库加载,并且可以使用刷新页面的提交按钮来执行搜索。但这不是我想要的,我不想刷新我希望它是动态的或者有些人称之为实时搜索。

这是我的 SessionController.php

    /**
 * @Route("/", name="app_session_index", methods={"GET", "POST"})
 * @param Request $request
 * @return Response
 */
public function index(Request $request): Response
{
    $propertySearch = new MyPropertySearch();
    //si si aucun nom n'est fourni on affiche tous les articles
    $sessions= $this->getDoctrine()->getRepository(Session::class)->findAll();
    $form = $this->createForm(PropertySearchType::class, $propertySearch);
    $form->handleRequest($request);
    //initialement le tableau des articles est vide,
    //c.a.d on affiche les articles que lorsque l'utilisateur clique sur le bouton rechercher
    $articles= [];

    if($form->isSubmitted() && $form->isValid()) {
        //on récupère le nom d'article tapé dans le formulaire
        $titre = $propertySearch->getTitle();
        if ($titre!="")
            //si on a fourni un nom d'article on affiche tous les articles ayant ce nom
            $sessions= $this->getDoctrine()->getRepository(Session::class)
                ->findByMultiple($titre);
    }
    return  $this->render('session/index.html.twig',[ 'form' =>$form->createView(), 'sessions' => $sessions]);
}

这是使用实体和我创建的名为 PropertySearchType.php 的表单。我不认为这是相关的。 然而,它正在使用

findByMultuple($titre)

方法,它是一种自定义 QueryBuilder 方法,用于使用多个条件搜索会话。

    /**
//  * @return Session[] Returns an array of Session objects
//  */

public function findByMultiple($searchValue)
{
    return $this->createQueryBuilder('s')
        ->join('s.coach', 'c')
        ->addSelect('c')
        ->where('s.title LIKE :title')
        ->orWhere('s.description LIKE :desc')
        ->orWhere('s.rating LIKE :rate')
        ->orWhere('c.tier LIKE :tier')
        ->setParameters(
            ['title' => $searchValue, 'tier'=>$searchValue,
                'desc'=>$searchValue, 'rate'=>$searchValue
            ])
        ->getQuery()
        ->getResult();
}

最后,它应该将我需要的内容输出到包含 javascript 和 ajax 必要的 session/index.html.twig 视图。 它确实会在我刷新时呈现所有会话和一个要写入的文本字段。但是当我写下我正在搜索的内容时,table 不会改变。

这是我正在渲染的树枝文件

    {% extends 'base.html.twig' %}
{% block title %}Session index{% endblock %}

{% block body %}
    <h1>Session index</h1>
    <h2>Search A Session !!</h2>

    <div class="sidebar-search">

        <div class="input-group custom-search-form">

            <input type="text" id="search" class="form-control" placeholder="Search here">
        </div>
    </div>
    <table class="table">
        <thead>
            <tr>
                <th>Id</th>
                <th>Title</th>
                <th>Description</th>
                <th>Date</th>
                <th>StartTime</th>
                <th>Link</th>
                <th>Rating</th>
                <th>actions</th>
            </tr>
        </thead>
        <tbody>
        {% for session in sessions %}
            <tr>
                <td>{{ session.id }}</td>
                <td>{{ session.title }}</td>
                <td>{{ session.description }}</td>
                <td>{{ session.date ? session.date|date('Y-m-d') : '' }}</td>
                <td>{{ session.startTime ? session.startTime|date('H:i:s') : '' }}</td>
                <td>{{ session.link }}</td>
                <td>{{ session.rating }}</td>
                <td>
                    <a href="{{ path('app_session_show', {'id': session.id}) }}">show</a>
                    <a href="{{ path('app_session_edit', {'id': session.id}) }}">edit</a>
                </td>
            </tr>
        {% else %}
            <tr>
                <td colspan="8">no records found</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
     <a href="{{ path('app_session_new') }}">Create new</a>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js">
    </script>
    <script type="text/javascript">
        jQuery( document ).ready(function() {
            var searchRequest = null;
            $("#search").keyup(function(e){
                /* La variable value va prendre la valeur insérer dans le champ de texte afin d’effectuer la recherche */
                var value = $(this).val();
                /* Ajax est lancé lors du remplissage du champ texte dont l’id est « search » pour faire la recherche */
                $.ajax({
                    /* l’url est une chaine de caractères contenant l’adresse où la requête est envoyée */
                    url :{{ path('searchSessions') }},
                    /* La méthode utilisée pour transférer les données est GET */
                    type : 'GET',
                    /*Ici search value va prendre la chaine entrée par un utilisateur dans la zone de recherche et sera placée après l’url */
                    data: {
                        'searchValue' : value
                    },
                    /*Cette fonction permet de vider le contenu du tableau pour recevoir le nouveau contenu*/
                    success : function(retour){
                        if(retour){
                            $('#t tbody#search').empty();
                            $.each(JSON.parse(retour), function(i, obj) {
                                $('#t tbody#all').hide();
                                $('#t tbody#search').append('<tr><td> '+obj.id+'  </td><td>    '+obj.title+'  </td>' +
                                    '<td>'+obj.description+' </td><td>'+obj.date+' </td><td>    '+obj.startTime+'  </td>' +
                                    '<td>    '+obj.link+'  </td><td>    '+obj.rating+'  </td>' +
                                    '<td><a href="/'+obj.id+'/edit">edit</a> </br>' +
                                    '<a href="/'+obj.id+'">remove</a></td></tr>');
    
                            });
                        }
                        else
                        {
                            $('#t tbody#all').show();
                            $('#t tbody#search').empty();
                            $('#t tbody#search').fadeIn('fast');
                        }``
                    },
                });
                return false;
            });
        });
    </script>
    {% endblock %}

Visual representation!!

我注意到的第一件事是在你的树枝代码中:你调用 {{ path('searchSessions') }} 但在你的 symfony 代码中定义的路由是 app_session_index.

使用 Postman(或其他类似软件)尝试您的 symfony 路径,如果它工作正常,则继续您的 javascript 代码。

否则你将无法找出问题的根源(或者需要更多时间:))

尝试隔离你的用例,如果你不知道执行了什么代码,你将无法调试。

正如我之前所说,使用 Postman 测试您的 back-end 代码,然后当我按照您的意愿工作时添加 AJAX 调用。

public function index(Request $request): Response
{
    $propertySearch = new MyPropertySearch();
    $form = $this->createForm(PropertySearchType::class, $propertySearch);
    $form->handleRequest($request);
    if($form->isSubmitted() && $form->isValid()) {
        // TEST IF YOU ARE PASSING HERE
        //on récupère le nom d'article tapé dans le formulaire
        $titre = $propertySearch->getTitle();
        // TEST IF TITLE IS CORRECT
        if ($titre!="") {
            // TEST IF findByMultiple WORK AS YOU WANT
            //si on a fourni un nom d'article on affiche tous les articles ayant ce nom
            $sessions= $this->getDoctrine()->getRepository(Session::class)
            ->findByMultiple($titre);
        }
    } else {
        // TEST IF YOU ARE PASSING HERE
        //si si aucun nom n'est fourni on affiche tous les articles
        $sessions= $this->getDoctrine()->getRepository(Session::class)->findAll();
    }
    return  $this->render('session/index.html.twig',[ 'form' =>$form->createView(), 'sessions' => $sessions]);
}