Faire une pagination symfony
Repository
/**
* Récupère une liste d'article paginés et triés par date de création.
*
* @param int $page Le numéro de la page
* @param int $nbMaxByPage Nombre maximum d'articles par page
*
* @throws InvalidArgumentException
* @throws NotFoundHttpException
*
* @return Paginator
*/
public function findAllPagedAndSorted($page, $nbMaxByPage)
{
if (!is_numeric($page)) {
throw new InvalidArgumentException(
'La valeur de l\'argument $page est incorrecte (valeur : ' . $page . ').'
);
}
if ($page < 1) {
throw new NotFoundHttpException('La page demandée n\'existe pas');
}
if (!is_numeric($nbMaxByPage)) {
throw new InvalidArgumentException(
'La valeur de l\'argument $nbMaxParPage est incorrecte (valeur : ' . $nbMaxByPage . ').'
);
}
$qb = $this->createQueryBuilder('article')
->orderBy('article.createdAt', 'DESC');
$query = $qb->getQuery();
$firstResult = ($page - 1) * $nbMaxByPage;
$query->setFirstResult($firstResult)->setMaxResults($nbMaxByPage);
$paginator = new Paginator($query);
if ( ($paginator->count() <= $firstResult) && $page != 1) {
throw new NotFoundHttpException('La page demandée n\'existe pas.'); // page 404, sauf pour la première page
}
return $paginator;
}
Controller
/**
* Liste les articles triés par date de création pour une page.
*
* @Route("/{page}", requirements={"page" = "\d+"}, name="article_index", methods={"GET"})
*
* @param int $page Le numéro de la page (par defaut 1)
*
*/
public function index(int $page = 1, ArticleRepository $articleRepository): Response
{
$nbArticleByPage = $this->getParameter('NB_ARTICLE_BY_PAGE');
$articles = $articleRepository->findAllPagedAndSorted($page, $nbArticleByPage);
$pagination = array(
'page' => $page,
'nbPages' => ceil(count($articles) / $nbArticleByPage),
'nomRoute' => 'article_index',
'paramsRoute' => array()
);
return $this->render('article/index.html.twig', [
'articles' => $articles,
'pagination' => $pagination
]);
}
NB_ARTICLE_BY_PAGE
est une constante que j’ai mis dans la config (.env)
/.env
NB_ARTICLE_BY_PAGE=20
/config/services.yaml
parameters:
NB_ARTICLE_BY_PAGE: '%env(resolve:NB_ARTICLE_BY_PAGE)%'
Vue (selector)
Dans la vue symfony voici le code à rajouter pour avoir un petit menu pour la navigation.
{% if pagination.nbPages > 0 %}
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center">
{% if pagination.page > 1 %}
<li class="page-item"><a class="page-link" href="{{ path(pagination.nomRoute, pagination.paramsRoute|merge({'page': 1})) }}">Debut</a></li>
<li class="page-item"><a class="page-link" href="{{ path(pagination.nomRoute,
pagination.paramsRoute|merge({'page': pagination.page-1})) }}">Précédent</a></li>
{% endif %}
{% for p in range(max(pagination.page-4, 1), min(pagination.page+4, pagination.nbPages)) %}
<li class="page-item {% if p == pagination.page %}active{% endif %}"><a class="page-link" href="{{ path(pagination.nomRoute, pagination.paramsRoute|merge({'page': p})) }}">{{p}}</a></li>
{% endfor %}
{% if pagination.page < pagination.nbPages %}
<li class="page-item"><a class="page-link" href="{{ path(pagination.nomRoute,
pagination.paramsRoute|merge({'page': pagination.page+1})) }}">Suivant</a></li>
<li class="page-item"><a class="page-link" href="{{ path(pagination.nomRoute,
pagination.paramsRoute|merge({'page': pagination.nbPages})) }}">Fin</a></li>
{% endif %}
</ul>
</nav>
{% endif %}