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 :
On peut ainsi naviguer dans les pages avec facilité.
Si on regarde le code dans le contrôleur Front/PostController :
On voit qu'on fait appel à la méthode getActiveOrderByDate du repository PostRepository :
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 :
{{
$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 :
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 :
Pour la sélection des nouveaux on utilise un paramètre dans l'URL :
http://monsite.com/admin/contacts?new=on
Du coup au niveau de la pagination il ne faut pas perdre ce paramètre :
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 :
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 :
$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 :
On voit qu'on :
- charge une relation (with(
'
ingoing
'
)) dont j'ai déjà parlé dans le chapitre sur le polymorphismeLe polymorphisme ; - quand (when) on a le paramètre new on filtre (has) les nouveaux contacts ;
- on active la pagination (paginate).
Si on en revient au code du trait :
$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 :
{{
$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 :
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 :
$(
'#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 :
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 :
{{
$posts
->
links('front.pagination'
) }}
Ce qui signifie qu'on utilise la vue front/pagination pour la mise en forme des liens de pagination :
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 :
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
=
"
#
"
>
«
<
/a
></li
>
@else
<
li><a href
=
"
{{
$paginator
->
previousPageUrl() }}
"
rel
=
"
prev
"
>
«
<
/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
"
>
»
<
/a
></li
>
@else
<
li class
=
"
disabled
"
><a href
=
"
#
"
>
»
<
/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.