Tutoriels Symfony + Twig 03 May 2026 13 min de lecture

Jour 9 - Ajouter recherche, filtres et pagination sans complexité

On rend le blog pratique avec recherche textuelle, filtres catégorie/tag et pagination propre côté Symfony.

Jour 9 - Ajouter recherche, filtres et pagination sans complexité - article technique

Dès que tu dépasses dix articles, un listing simple ne suffit plus. Il faut un vrai parcours de navigation.

On met en place une recherche simple mais utile, et une pagination propre.

Objectif d’apprentissage

Permettre aux lecteurs de trouver rapidement un article via recherche et filtres, avec une pagination claire et SEO-friendly.

Ce que tu vas pratiquer aujourd’hui

  • Ajouter un champ de recherche GET.
  • Filtrer par catégorie ou tag.
  • Paginer proprement côté repository.
  • Conserver des URLs propres et partageables.

1. Créer la requête paginée côté repository

Évite de charger toute la table en mémoire. La pagination doit être gérée dans la requête SQL.

Garde une méthode dédiée au listing filtré.

public function findPublishedPaginated(?string $search, int $limit, int $offset): array
{
    $qb = $this->createQueryBuilder('post')
        ->andWhere('post.status = :status')
        ->setParameter('status', BlogPost::STATUS_PUBLISHED)
        ->orderBy('post.publishedAt', 'DESC');

    if ($search) {
        $qb->andWhere('post.title LIKE :q OR post.excerpt LIKE :q')
           ->setParameter('q', '%' . $search . '%');
    }

    return $qb->setMaxResults($limit)->setFirstResult($offset)->getQuery()->getResult();
}

2. Lire les filtres dans le controller

On lit la query string en GET pour garder des URLs indexables et partageables.

La logique reste simple: parser, compter, récupérer.

$q = trim((string) $request->query->get('q', ''));
$page = max(1, $request->query->getInt('page', 1));
$perPage = 9;
$offset = ($page - 1) * $perPage;

$posts = $blogPostRepository->findPublishedPaginated($q !== '' ? $q : null, $perPage, $offset);

3. Afficher la pagination en Twig

Génère les liens de pagination avec les filtres actifs pour ne pas perdre le contexte utilisateur.

Évite les liens cassés ou les pages vides.

{% for i in 1..pagination.totalPages %}
    <a href="{{ path('app_blog_index', queryFilters|merge({page: i})) }}"
       class="{{ i == pagination.currentPage ? 'is-active' : '' }}">
        {{ i }}
    </a>
{% endfor %}

Checklist de fin de session

  • Recherche GET fonctionnelle.
  • Pagination côté SQL en place.
  • Liens de pages corrects.
  • Filtres conservés lors de la navigation.

Erreurs fréquentes à éviter

  • Sauter la vérification finale parce que “ça marche chez moi”.
  • Mélanger trop de logique dans le controller au lieu de garder un flux clair.
  • Oublier la cohérence entre la donnée, le template Twig et le comportement en production.

Pourquoi cette étape compte en conditions réelles

Dans un vrai projet client, chaque étape technique doit rester compréhensible par l’équipe, duplicable sur un autre environnement et fiable dans le temps. Ici, l’objectif est de transformer la théorie en un flux de travail concret, avec des décisions simples que tu peux défendre en revue de code.

Si tu appliques sérieusement les points du jour (ajouter un champ de recherche get.), tu réduis la dette technique dès le départ et tu facilites la suite: SEO, publication, maintenance et déploiement. C’est exactement la différence entre un blog “démo” et un blog exploitable en production.

Mini plan de révision

  • Reprends ce point et explique-le à voix haute comme si tu faisais un code review : Ajouter un champ de recherche GET.
  • Reprends ce point et explique-le à voix haute comme si tu faisais un code review : Filtrer par catégorie ou tag.
  • Reprends ce point et explique-le à voix haute comme si tu faisais un code review : Paginer proprement côté repository.

Exercice rapide

Ajoute un filtre “temps de lecture max” pour les lecteurs qui veulent des formats courts.

Et demain ?

Demain, on traite le SEO on-page: metas dynamiques, canonical et JSON-LD minimal.

Partager

Faire circuler cet article

Si ce contenu peut aider quelqu’un dans son projet, tu peux le partager directement.

LinkedIn X WhatsApp

Tu dois structurer un backend, clarifier une API ou reprendre un existant en production ?

Échanger sur ton besoin