Cours Laravel 5.5 – les données – la pagination
Jeudi 28 septembre 2017 14:11
La pagination consiste à limiter le nombre de données affichées et de 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 vois dans ce chapitre comment faire.
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 :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 :
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).
{{ $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=2Donc on a en paramètre de l'url le numéro de la page désirée.
Ajouter (appends) des paramètres à la pagination
Il arrive qu'on ai 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=onDu coup au niveau de la pagination il ne faut pas perdre ce paramètre :
http://monsite.com/admin/contacts?new=on&page=2Voyons 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 :
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 pou 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 :
public function getAll($nbrPages, $parameters)
{
return Contact::with ('ingoing')
->latest()
->when ($parameters['new'], function ($query) {
$query->has ('ingoing');
})->paginate($nbrPages);
}
On voit qu'on :
- charge une relation (with('ingoing')) dont j'ai déjà parlé dans le chapitre sur le polymorphisme,
- quand (when) on a le paramètre new on filtre (has) les nouveaux contacts,
- on active la pagination (paginate).
$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 }}
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 régénérée. Toujours dans la méthode index du trait qu'on a vu ci-dessus on a ce code :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) issu 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).
$('#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.
La personnalisation de la vue de la pagination
Par défaut la vue de génération des liens de la pagination correspondant à 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-paginationOn 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 :
@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 :
@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.
En résumé
- La pagination avec Laravel se fait simplement avec la méthode paginate.
- On peut ajouter des paramètres aux urls 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.
Par bestmomo
Nombre de commentaires : 4