Hello web developers .

Je suis sur un projet web et je cherche la manière la plus propre pour mettre en place un moteur de recherche avec pagination des résultats.

Ce projet consiste à rechercher des données dont l'adresse complète est enregistré.
Concernant la gestion des adresses, j'ai décidé de modéliser une table pour l'adresse, une pour la ville, une pour le département et la région puis une autre pour le pays.
Je dispose donc d'un mld de ce genre :

  • adresse(id, ..., adresse, #ville_id) // 92-98 Boulevard Victor Hugo
  • ville(id, nom, cp, adresse_id) // 92110 Clichy
  • departement(id, nom, region_id) // Hauts-de-Seine
  • region(id, nom, pays_id) // Île-de-France
  • pays(id, nom) // France



D'entrée de jeu je me pose la question :
Quelle méthode utiliser pour ce formulaire, POST ou GET ?
Quelque recherche mon permis de découvrir que la plupart des cas utilisés la méthode GET.
Cependant j'ai utilisé la méthode POST, car je me sers de l'hydratation de formulaire avec l'api google maps.
En effet celle-ci me permet d'hydrater les champs de mon formulaire à l'aide du composant componentForm.

Api : https://developers.google.com/maps/d...ressform?hl=fr

Sur moteur de recherche j'inclue donc l'api google maps (Place Autocomplete Address Form) afin de bénéficier de l'auto complétion des adresses maps.

Côté client j'utilise l'architecture informatique Ajax à l'aide de la bibliothèque jQuery et plus particulièrement la méthode jQuery.ajax() pour la pagination.
Et la méthode $.post pour le formulaire de recherche.

Côté serveur j'utilise le bundle KnpPaginatorBundle (https://github.com/KnpLabs/KnpPaginatorBundle) pour générer mes résultats paginés.
Et le composant FormBuilder de symfony pour la génération du formulaire.

Je souhaite donc ici afficher mes résultats lors de la soumission du formulaire.
Puis afficher les résultats suivants sans avoir à recharger la page lors du clic d'un nouveau numéro de page.

Cependant, je n'arrive pas à conserver mes résultats lors du passage à la seconde page.

Ici j'avais comme idée d'utiliser les sessions pour enregistrer les données de mon formulaire mais j'ai décidé d'abandonner cette méthode, car pour moi je ne pense pas que ce soit la bonne méthode.

En ce qui concerne la pagination elle fonctionne correctement en ajax, j'ai pu la tester avec des résultats pré-chargés dans la méthode du contrôleur.

Voici des extraits de code :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
 
// index.html.twig
 <div id="displayResults">
// Et les templates incluent qui vont suivre  :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
// Template twig utilisé pour la pagination par le bundle knpPaginatorBundle (custom_pagination.html.twig)
{% if pageCount > 1 %}
    <nav>
        <ul class="pagination">
            {% if previous is defined %}
                <li class="page-item">
                    <a class="page-link" data-page="{{ previous }}" href="#" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                        <span class="sr-only">Previous</span>
                    </a>
                </li>
            {% endif %}
            {% for page in pagesInRange %}
                {% if page != current %}
                    <li class="page-item"><a class="page-link" data-page="{{ page }}" href="#">{{ page }}</a></li>
                {% else %}
                    <li class="page-item active"><a class="page-link">{{ page }}</a></li>
                {% endif %}
            {% endfor %}
            {% if next is defined %}
                <li class="page-item">
                    <a class="page-link" data-page="{{ next }}" href="#" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                        <span class="sr-only">Next</span>
                    </a>
                </li>
            {% endif %}
        </ul>
    </nav>
{% endif %}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Template du formulaire
{{ form_start(form, {'attr': {'id':'address_search', 'class': 'form-inline', 'role' : 'search' }}) }}
    {{ form_errors(form) }}
 
    {{ form_row(form.address, {'id':'autocomplete', 'attr': {'placeholder':'Enter an address, a city, postal code'}}) }}
 
    {# Hidden fields #}
    {{ form_row(form.streetNumber, {'id':'street_number'}) }}
    {{ form_row(form.route, { 'id': 'route'}) }}
    {{ form_row(form.latitude, { 'id': 'lat'}) }}
    {{ form_row(form.longitude, { 'id': 'lng'}) }}
    {{ form_row(form.city, { 'id': 'locality'}) }}
    {{ form_row(form.postalCode, { 'id': 'postal_code'}) }}
    {{ form_row(form.department, { 'id': 'administrative_area_level_2'}) }}
    {{ form_row(form.region, { 'id': 'administrative_area_level_1'}) }}
    {{ form_row(form.country, { 'id': 'country'}) }}
 
     {{ form_row(form.search, {'attr': {'class':'btn btn-primary'}}) }}
{{ form_end(form) }}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Méthode ajax du formulaire
$('#search').on('submit', function(e) {
        e.preventDefault();
        var $this = $(this); // The jQuery object of the form
 
        $.ajax({
            url: Routing.generate('search'), // méthode du bundle FOSJsRoutingBundle
            type: 'POST',
            data: $this.serialize(), // Serializing form data
            success: function( result ) {
                var elem =  document.getElementById('displayResults');
                elem.innerHTML = "";
                elem.innerHTML = result;
            }
        });
});
 
// Méthode ajax pour la pagination
$('body').on('click', 'a.page-link', function(e) {
        e.preventDefault();
        var page = $(this).attr('data-page');
 
        $.ajax({
            type: "POST",
            url: Routing.generate('index'),
            data: { "page" : page },
            cache: false,
            success: function(result){
                var elem =  document.getElementById('displayResults');
                elem.innerHTML = "";
                elem.innerHTML = result;
            }
        });
 });
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 // Méthodes du controlleur 
 public function indexAction(Request $request)
    {
        $form = $this->createForm(AddressSearchType::class);
 
        $em = $this->getDoctrine()->getManager();
        $res = $em->getRepository('CoreBundle:MyEntity')->findByLocation(); // Récupère les résultats en fonction de la location de l'utilisateur
 
        $pagination = $this->pagination(
            $res,
            $request->get('page', 1)
        );
 
        if ($request->isXmlHttpRequest())
        {
            return new Response($this->renderView('CoreBundle:MyEntity:list.html.twig', array('pagination' => $pagination))); // parameters to template
        }
 
        return $this->render('CoreBundle:MyEntity:index.html.twig', [
            'form' => $form->createView(),
            'pagination' => $pagination
        ]);
    }
 
public function searchAction(Request $request)
{
	if($request->isXmlHttpRequest())
        {
            $data = $request->get('address_search'); // Requête pour récupérer les données du formulaire sérialisé 
            $em = $this->getDoctrine()->getManager();
            // $data['query_request'] // User input, verify validation rules
 
            $res = $em->getRepository('CoreBundle:MyEntity')->findByAddress($data);
 
            $pagination = $this->pagination(
                $res,
                $request->get('page', 1)
            );
 
            return new Response($this->renderView('CoreBundle:MyEntity:list.html.twig', array('pagination' => $pagination)));
        }
}
 
private function pagination($data, $page, $limit = 2)
    {
        $paginator  = $this->get('knp_paginator');
 
        $pagination = $paginator->paginate($data, $page, $limit);
        $pagination->setTemplate('CoreBundle:Template:custom_pagination.html.twig');
 
        return $pagination;
    }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Routes
index:
    path:     /my_uri/
    defaults:
        _controller: CoreBundle:MyEntity:index
    options:
        expose: true
 
#test#
search:
    path:  /my_uri/search
    defaults:
        _controller: CoreBundle:MyEntity:search
    options:
        expose: true
Merci d'avance pour vos soutiens.