Pagination avec Symfony2 et PagerFanta !
mai 11, 2011 10 Commentaires
Symfony2 Beta1 est sorti depuis quelques semaines, tout va bien !
Alors que je me demandais comment fonctionnait un Bundle je constate qu’il utilise un Pager! Oh, de la pagination! Voilà un sujet intéressant !
Alors le but n’est pas de vous expliquer en profondeur comment va fonctionner le pager, la classe est tellement simple que je vous laisse la découvrir !
Installation
On va installer un Bundle et PagerFanta! PagerFanta est le système de pagination en lui-même, et le Bundle ne fera que gérer la vue et la personnalisation de PagerFanta.
git submodule add http://github.com/whiteoctober/Pagerfanta.git vendor/pagerfanta git submodule add http://github.com/whiteoctober/WhiteOctoberPagerfantaBundle.git vendor/bundles/WhiteOctober/PagerfantaBundle
On enregistre les namespaces:
// app/autoload.php $loader->registerNamespaces(array( // ... 'WhiteOctober\PagerfantaBundle' => __DIR__.'/../vendor/bundles', 'Pagerfanta' => __DIR__.'/../vendor/pagerfanta/src', // ... ));
Puis on enregistre le Bundle
// app/AppKernel.php
public function registerBundles()
{
return array(
// ...
new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
// ...
);
}
Utilisation
Je pars du principe que vous avez un Bundle, un Controller et une Vue ! Et une base de données ! Dans mon cas ça sera Mysql.
PagerFanta fonctionne en utilisant le Pattern Adaptateur, c’est-à-dire qu’on peut utiliser n’importe quelles classes implémentant l’interface AdapterInterface. On pourra ainsi utiliser Doctrine ORM ou ODM ou d’autres, tant qu’on se débrouille pour renvoyer le résultat.
Premièrement on instancie un nouvel objet Adaptateur: DoctrineORMAdapter dans lequel on passe une instance de queryBuilder. C’est la requête que l’on effectuera pour récupérer notre contenu.
On passe ensuite l’objet DoctrineORMAdapter au constructeur de PagerFanta.
A partir de là, on peut commencer à personnaliser notre objet de pagination:
$pagerfanta->setMaxPerPage($maxPerPage); // 10 par défaut $maxPerPage = $pagerfanta->getMaxPerPage(); $pagerfanta->setCurrentPage($currentPage); // 1 par défaut $currentPage = $pagerfanta->getCurrentPage(); $nbResults = $pagerfanta->getNbResults(); $currentPageResults = $pagerfanta->getCurrentPageResults(); $pagerfanta->getNbPages(); $pagerfanta->haveToPaginate(); $pagerfanta->hasPreviousPage(); $pagerfanta->getPreviousPage(); $pagerfanta->hasNextPage(); $pagerfanta->getNextPage();
Grâce à ses méthodes on dispose de toutes les informations qu’il nous faut pour effectuer nos paginations.
Dans la vue
Pour générer la pagination, c’est-à-dire les liens entre chaque page, le Bundle PagerFantaBundle propose une méthode pour twig:
{{ pagerfanta(pagerfanta, 'default') }}
On lui passe notre objet pagerfanta, et on lui applique une vue par défaut.
Pour afficher la liste du contenu, on va appeler une boucle sur l’objet pagerfanta que l’on passera dans le Controller:
{% for data in pagerfanta.currentPageResults %}
<li>{{ data }}</li>
{% endfor %}
On va ainsi afficher les résultats de la page courante, par page je parle toujours des données découpées par la pagination.
Le Controller
Dans la vue, chaque lien généré aura une URL de la sorte : ma-route/?page=x, où x est le numéro de la page.
Lorsqu’on clic sur le lien, il faut récupérer cette valeur dans notre controller. Pour cela on utilise le service request:
$request = $this->get('request');
$page = $request->query->get('page',1);
try {
$pagerfanta->setCurrentPage($page);
} catch (NotValidCurrentPageException $e) {
throw new NotFoundHttpException();
}
$request->query->get(‘page’,1) nous permet de récupérer la valeur de page, et le second argument est la valeur par défaut.
Voici le code de mon Controller:
// pagination
$queryBuilder = $em->createQueryBuilder()
->select('u')
->from('NaN\ArticlesBundle\Entity\Articles', 'u');
$adapter = new DoctrineORMAdapter($queryBuilder);
$pagerfanta = new Pagerfanta($adapter);
$pagerfanta->setMaxPerPage(8); // 8 résultats par page
$request = $this->get('request');
$page = $request->query->get('page',1);
try {
$pagerfanta->setCurrentPage($page);
} catch (NotValidCurrentPageException $e) {
throw new NotFoundHttpException();
}
return array('pagerfanta' => $pagerfanta);
Ainsi on vient de voir comment utiliser simplement et rapidement un système de pagination pour Symfony2 !
Les sources des projets comportent des détails pour personnaliser les paginations, à lire
!
Hello,
Dans mon projet en cours, j’ai une relation one-to-many entre mon entité “Product” et mon entité “Picture”. J’utilise le paginator de KnpLabs qui me permet de mettre une limite sur le nombre de produits retournés, et non pas le nombre de lignes de résultats (sans ce paginator, si chaque produit a par exemple 5 images, un “limit 10″ ne me retournera que 2 produits…)
Est-ce que tu sais si PagerFanta gère également correctement les limit lors qu’il y a des relation one-to-many ?
Merci pour l’article en tout cas !
Je suis pas sûr d’avoir suivis ce que tu essaies d’expliquer, montres ta requête de base si tu veux ^^
il n’y aurai pas quelque chose à faire pour définir la méthode dans twig, car j’ai cette erreur “The function “pagerfanta” does not exist in ….html.twig at line 40 “?
Sinon les datas s’affichent bien ça me semble facile à utiliser, j’ai juste ce petit problème qui m’empêche de générer les liens de pagination :-/
Tu es sûr d’avoir installé correctement le bundle ? Parce que s’il ne trouve pas la fonction pagerfanta dans ton template, c’est qu’il ne trouve pas l’extension proposée par le bundle…Essaies de bien relire l’installation et mettre tes sources à jour. Autant pour le pager, que symfony et twig.
Ok je vois
J’ai essayer d’inclure l’extension dans la config config.yml de mon projet et là j’ai eu un MSG m’indiquant que l’extension était introuvable. Ça concorde avec ce que tu me dis
Ok en fait le problème était situé entre le clavier et le fauteuil :/
Bonjour,
Ce pager est-il toujours utilisable avec Symfony 2 RC4 ?
Car j’ai l’impression d’avoir fait exactement ce que tu indiques mais ça ne marche pas …
Y a t-il des “use” à mettre dans le contrôleur ? car le message d’erreur m’indique qu’il ne trouve pas la classe pour DoctrineORMAdapter.
D’avance merci
Vous pouvez oublier le message précédent le problème se situait également entre le clavier et le fauteuil TT
Par contre comment peut on changer les mots “Previous” et “Next”, ajouter un peu d’espace entre les chiffres, etc. ?
D’après la page sur github lien, tout en bas il explique la marche à suivre. Il faut modifier le css pour gérer l’espacement, et pour changer les noms utiliser la classe OptionablView:
$myView2 = new OptionableView($defaultView, array('previous_message' => 'Anterior', 'next_message' => 'Siguiente'));Bonjour,
Merci pour cet article très intéressant. J’ai repris exactement ce que tu as dit et tout fonctionne parfaitement.
Cependant, j’ai voulu paginer les résultats d’une recherche. J’ai la première page qui s’affiche parfaitement, mais lorsque je clic sur la page 2 ou 3, je perds la valeur de recherche et donc il n’y a plus aucun résultats, et je perds la valeur requête.
Est-ce que le bundle contient un truc pour faire passer en plus du numéro de la page la requête pour pouvoir la récupérer ? Ou as-tu déjà eu un truc semblable à réaliser ?
Bien à toi,
Thibault