Cours pour apprendre à utiliser le framework Laravel 5.5

Les données


précédentsommairesuivant

IX. La pagination

La pagination consiste à limiter le nombre de données affichées et à prévoir des boutons de navigation entre les pages ainsi constituées. Laravel propose une pagination automatique facile à mettre en œuvre aussi bien au niveau du Query Builder que d'Eloquent. Nous allons voir dans ce chapitre comment faire.

IX-A. Paginer (paginate) le résultat d'une requête

Dans l'application d'exemple en page d'accueil on a 6 articles présentés accompagnés d'une pagination :

Image non disponible

On peut ainsi naviguer dans les pages avec facilité.

Si on regarde le code dans le contrôleur Front/PostController :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
public function index()
{
    $posts = $this->postRepository->getActiveOrderByDate($this->nbrPages);

    return view('front.index', compact('posts'));
}

On voit qu'on fait appel à la méthode getActiveOrderByDate du repository PostRepository :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
protected function queryActiveOrderByDate()
{
    return $this->model
        ->select('id', 'title', 'slug', 'excerpt', 'image')
        ->whereActive(true)
        ->latest();
}

...

public function getActiveOrderByDate($nbrPages)
{
    return $this->queryActiveOrderByDate()->paginate($nbrPages);
}

Dans la méthode queryActiveOrderByDate on :

  • sélectionne (select) les colonnes nécessaires ;
  • filtre (whereActive) uniquement les articles actifs (true) ;
  • ordonne à partir du plus récent (latest).

Dans la méthode getActiveOrderByDate on reçoit en paramètre le nombre d'articles à afficher pour chaque page et on utilise la méthode paginate sur la requête pour avoir automatiquement le bon nombre d'enregistrements.

Au niveau de la vue front/index.blade.php on a ce code :

 
Sélectionnez
{{ $posts->links('front.pagination') }}

La méthode links génère la pagination. Par défaut elle ne nécessite pas de paramètre, on verra plus loin pourquoi ici on lui transmet une vue.

Si vous avez la curiosité de regarder comment sont constitués les liens de la pagination vous allez voir quelque chose de cette forme :

 
Sélectionnez
http://monsite.com/?page=2

Donc on a en paramètre de l'URL le numéro de la page désirée.

IX-B. Ajouter (appends) des paramètres à la pagination

Il arrive qu'on ait besoin d'ajouter des paramètres à l'URL de la pagination. Regardez dans l'administration la liste des contacts en sélectionnant les nouveaux :

Image non disponible

Pour la sélection des nouveaux on utilise un paramètre dans l'URL :

 
Sélectionnez
http://monsite.com/admin/contacts?new=on

Du coup au niveau de la pagination il ne faut pas perdre ce paramètre :

 
Sélectionnez
http://monsite.com/admin/contacts?new=on&page=2

Voyons comment on fait ça…

On a vu que pour la gestion des pages d'index des différentes entités il est fait usage du trait Back/Indexable. Dans ce trait on a la méthode qui gère la liste des entités :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
public function index(Request $request)
{
    $parameters = $this->getParameters ($request);

    // Get records and generate links for pagination
    $records = $this->repository->getAll (config ("app.nbrPages.back.$this->table"), $parameters);
    $links = $records->appends ($parameters)->links ('back.pagination');

    // Ajax response
    if ($request->ajax ()) {
        return response ()->json ([
            'table' => view ("back.$this->table.table", [$this->table => $records])->render (),
            'pagination' => $links->toHtml (),
        ]);
    }

    return view ("back.$this->table.index", [$this->table => $records, 'links' => $links]);
}

Comme ça concerne plusieurs entités aux paramètres variables on a une méthode getParameters qui va chercher ces paramètres. Ce qui nous intéresse pour ce chapitre c'est cette partie du code :

 
Sélectionnez
$records = $this->repository->getAll (config ("app.nbrPages.back.$this->table"), $parameters);
$links = $records->appends ($parameters)->links ('back.pagination');

On va chercher les enregistrements (getAll) dans le repository en transmettant le nombre de pages issu de la configuration (config("app.nbrPages.back.$this->table")) ainsi que les paramètres.

Comme on a affaire aux contacts c'est dans ce cas le repository ContactRepository :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
public function getAll($nbrPages, $parameters)
{
    return Contact::with ('ingoing')
        ->latest()
        ->when ($parameters['new'], function ($query) {
            $query->has ('ingoing');
        })->paginate($nbrPages);
}

On voit qu'on :

Si on en revient au code du trait :

 
Sélectionnez
$links = $records->appends ($parameters)->links ('back.pagination');

On voit qu'on utilise la méthode appends pour ajouter le paramètre new, ensuite on utilise la méthode links qu'on a déjà vue ci-dessus.

Du coup dans la vue back/contacts/index.blade.php on a juste ce code pour générer la pagination :

 
Sélectionnez
{{ $links }}

IX-C. La pagination en Ajax

Toujours avec la vue d'administration des contacts vous avez sans doute remarqué que le changement de page se fait en Ajax, c'est juste la liste des contacts qui est regénérée.

Toujours dans la méthode index du trait qu'on a vu ci-dessus on a ce code :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
if ($request->ajax ()) {
    return response ()->json ([
        'table' => view ("back.$this->table.table", [$this->table => $records])->render (),
        'pagination' => $links->toHtml (),
    ]);
}

Si la requête est en Ajax (ajax) alors on retourne une réponse JSON (response()->json) avec deux éléments :

  • la liste (table) issue de la vue dont on génère le code HTML (render) ;
  • la pagination (pagination) avec les liens dont on a vu la génération ci-dessus et qu'on envoie au format HTML (toHtml).

Il suffit côté client de regénérer les parties de la page correspondante :

 
Sélectionnez
$('#pannel').html(data.table)
$('#pagination').html(data.pagination)

Je parlerai plus en détail de l'utilisation d'Ajax avec Laravel dans un chapitre ultérieur.

IX-D. La personnalisation de la vue de la pagination

Par défaut la vue de génération des liens de la pagination correspond à une mise en forme pour Bootstrap. Quand on l'utilise c'est parfait et on n'a rien à faire. Par contre quand on désire une autre mise en forme, comme c'est le cas pour l'application d'exemple on a un peu plus de travail.

Une solution consiste à publier les vues de Laravel avec la commande :

 
Sélectionnez
php artisan vendor:publish --tag=laravel-pagination

On se retrouve avec les vues dans le dossier resources/views/vendor/pagination et il ne reste plus qu'à les modifier.

Une autre solution que j'ai adoptée pour l'application est de passer le nom de la vue à la méthode links. Par exemple pour la page d'accueil on a ce code dans la vue :

 
Sélectionnez
{{ $posts->links('front.pagination') }}

Ce qui signifie qu'on utilise la vue front/pagination pour la mise en forme des liens de pagination :

 
Sélectionnez
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.
@if ($paginator->hasPages())
    <nav class="pagination">
        {{-- Previous Page Link --}}
        @if ($paginator->onFirstPage())
            <span class="page-numbers prev inactive">@lang('pagination.previous')</span>
        @else
            <a href="{{ $paginator->previousPageUrl() }}" class="page-numbers prev" rel="prev">@lang('pagination.previous')</a>
        @endif

        {{-- Pagination Elements --}}
        @foreach ($elements as $element)
            {{-- "Three Dots" Separator --}}
            @if (is_string($element))
                <span class="page-numbers current">{{ $element }}</span>
            @endif

            {{-- Array Of Links --}}
            @if (is_array($element))
                @foreach ($element as $page => $url)
                    @if ($page == $paginator->currentPage())
                        <span class="page-numbers current">{{ $page }}</span>
                    @else
                        <a href="{{ $url }}" class="page-numbers">{{ $page }}</a>
                    @endif
                @endforeach
            @endif
        @endforeach

        {{-- Next Page Link --}}
        @if ($paginator->hasMorePages())
            <a href="{{ $paginator->nextPageUrl() }}"  class="page-numbers next" rel="next">@lang('pagination.next')</a>
        @else
            <span class="page-numbers next inactive">@lang('pagination.next')</span>
        @endif
    </nav>
@endif

Pour la partie administration on a une autre mise en forme et donc une autre vue back/pagination :

 
Sélectionnez
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.
@if ($paginator->hasPages())
    <ul class="pagination pagination-sm no-margin pull-right">
        {{-- Previous Page Link --}}
        @if ($paginator->onFirstPage())
            <li class="disabled"><a href="#">&laquo;</a></li>
        @else
            <li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">&laquo;</a></li>
        @endif

        {{-- Pagination Elements --}}
        @foreach ($elements as $element)
            {{-- "Three Dots" Separator --}}
            @if (is_string($element))
                <li class="disabled"><a href="#">{{ $element }}</a></li>
            @endif

            {{-- Array Of Links --}}
            @if (is_array($element))
                @foreach ($element as $page => $url)
                    @if ($page == $paginator->currentPage())
                        <li class="active"><a href="#">{{ $page }}</a></li>
                    @else
                        <li><a href="{{ $url }}">{{ $page }}</a></li>
                    @endif
                @endforeach
            @endif
        @endforeach

        {{-- Next Page Link --}}
        @if ($paginator->hasMorePages())
            <li><a href="{{ $paginator->nextPageUrl() }}" rel="next">&raquo;</a></li>
        @else
            <li class="disabled"><a href="#">&raquo;</a></li>
        @endif
    </ul>
@endif

On a toujours la même structure mais ce sont les classes utilisées qui changent selon l'aspect voulu.

IX-E. En résumé

  • La pagination avec Laravel se fait simplement avec la méthode paginate.
  • On peut ajouter des paramètres aux URL de pagination avec la méthode appends.
  • On peut facilement réaliser une pagination en Ajax.
  • Il faut créer une vue particulière pour la pagination si on n'utilise pas Bootstrap.

précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2018 Laravel. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.