Encore de la pagination, paginator de chez knplabs (et Zend!)
mai 12, 2011 18 Commentaires
Dans l’article précédent je vous présentais pagerFantaBundle, un système de pagination simple d’utilisation et performant. Aujourd’hui on va utiliser et comparer le Bundle paginatorBundle.
La principale différence, si on peut dire, est l’utilisation de la librairie Paginator de chez ZendFramework.
La seconde différence c’est que si on utilise ORM les requêtes seront optimisées, ce qui n’est pas encore le cas avec pagerFanta, mais c’est prévu selon l’auteur.
Installation
Commencez par télécharger ZendFramework (ZF) avec github:
git submodule add git://github.com/zendframework/zf2.git vendor/Zend
Téléchargez également paginatorBundle en ajoutant ceci dans votre fichier deps:
[PaginatorBundle]
git=http://github.com/knplabs/KnpPaginatorBundle.git
target=/bundles/Knp/Bundle/PaginatorBundleEt dans deps.lock on indique le dernier commit:
PaginatorBundle bc53101d8a3e52d799e0fb04de9e44d6f5ac2599
On active le tout dans l’autoload.php:
'Knp' => __DIR__.'/../vendor/bundles', 'Zend' => __DIR__.'/../vendor/Zend/library',
Et on a active le Bundle dans appKernel:
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),,
Dans config.yml ou votre fichier de configuration xml/php, ajouter cette ligne:
knp_paginator:
templating: ~ # active la vue et helper pour twigtemplating peut prendre la clé template afin de lui indiquer quelle vue sera utilisée pour représenter la pagination, par défaut on utilise KnplabsPaginatorBundle:Pagination:sliding.html.twig.
Utilisation
Controller
Voici ce que j’ai dans mon controller:
$queryBuilder = $em->createQueryBuilder()
->select('u')
->from('NaN\Articles\Entity\Article', 'u');
$query = $queryBuilder->getQuery();
$adapter = $this->get('knp_paginator.adapter');
$adapter->setQuery($query);
$adapter->setDistinct(true);
$paginator = new\Zend\Paginator\Paginator($adapter);
$paginator->setCurrentPageNumber($this->get('request')->query->get('page', 1));
$paginator->setItemCountPerPage(10);
$paginator->setPageRange(6);Ne pas oublier de faire les imports des classes.
On voit ici que Paginator prends un objet implémentant une classe Adaptateur, le Bundle possédant une classe implémentant cette interface.
Vue
Pour la vue, on va voir que le Bundle propose également la possibilité de trier les colonnes, ceci ce fait par le filtre sortable. Voici la vue:
<table>
<tr>
{# trie par colonnes #}
<th>{{ paginator|sortable('Id', 'u.id') }}</th>
<th>{{ paginator|sortable('Title', 'u') }}</th>
</tr>
{% for article in paginator %}
<tr {% if loop.index is odd %}class="color"{% endif %}>
<td>{{ article.id }}</td>
<td>{{ article }}</td>
</tr>
{% endfor %}
</table>
{# pagination #}
<div id="navigation">
{{ paginator|paginate }}
</div>
On remarque que sortable prends en paramètre l’objet Paginator, le nom de la colonne et la référence que l’on a écrite dans le controller, par exemple u.id, si on écrivait p.id, ça ne marcherait pas.
Pour le titre je passe juste ‘u’, car je souhaite obtenir la valeur de ma méthode __toString() de mon entité.
Customisation
Je vous montre juste comment personnaliser la route, pour le moment on a quelque chose du genre:
monsite.com/articles/?page=2
Mais moi j’aimerai plutôt avoir:
monsite.com/articles/liste-des-articles-page-2-sur-15
Cela implique de modifier votre route dans le controller ou votre fichier routing, pour avoir quelque chose comme ça:
/**
*@extra:Route("/liste-des-articles-pages-{page}-sur-{nbre}", name="listeA")
**/
public function indexAction($page, $nbre)
Puis, on va créer notre vue, plusieurs choix sont possibles, soit on créé la vue dans notre Bundle où on veut, soit on surcharge la vue du Bundle Paginator. Moi je choisis la seconde option, pour cela dans le dossier app/Resources, on va créer les dossiers KnpPaginatorBundle/views/Pagination et on y copie le fichier original sliding.html.twig.
A partir de là on peut modifier comme on souhaite la vue:
{# default Sliding pagination control implementation #}
{% if pageCount > 1 %}
<div class="pagination">
{% if first is defined and current != first %}
<span class="first">
<a href="{{ path(route, query|merge({'page': first, 'nbre': last})) }}">Début</a>
</span>
{% endif %}
{% if previous is defined %}
<span class="previous">
<a href="{{ path(route, query|merge({'page': previous, 'nbre': last})) }}">Précédent</a>
</span>
{% endif %}
{% for page in pagesInRange %}
{% if page != current %}
<span class="page">
<a href="{{ path(route, query|merge({'page': page, 'nbre': last})) }}">{{ page }}</a>
</span>
{% else %}
<span class="current">{{ page }}</span>
{% endif %}
{% endfor %}
{% if next is defined %}
<span class="next">
<a href="{{ path(route, query|merge({'page': next, 'nbre': last})) }}">Suivant</a>
</span>
{% endif %}
{% if last is defined and current != last %}
<span class="last">
<a href="{{ path(route, query|merge({'page': last, 'nbre': last})) }}">Fin</a>
</span>
{% endif %}
</div>
{% endif %}
J’ai également fait un merge dans le tableau query de chaque lien, en ajoutant les propriétés page et nbre. Les valeurs passées en argument sont définies dans le fichier Paginator.php de Zend.
On obtient ainsi des urls propres et jolies !
J’espère que tout aura été clair et fonctionnera chez vous ! N’hésitez pas à laisser un commentaire !
Nice article, there are some missing elements at the end of it, perhaps you can github this source code example too please?
The adapter class I guess is included in the PaginatorBundle? It was not very clear…
Thanks,
Ping : Symfony2 Paginator with Zend Git into Vendors! | Craft It Online!
One more thing, I think you said you were going to compare PagerFanta with this Paginator but you did not?
So can you tell me please, which one you liked the best?
Thanks!
I answered quickly in the article, I said with Zend queries were optimized
Thank you for this article. Even with my limited French, j’ai franchement compris tout l’article sans probleme!
I’m hoping that by affiliating myself with Symfony2, I will have more opportunities to read and polish my French!
Would you, by any remote chance, have come across any code examples which integrate custom filtering with the PaginatorBundle?
Merci.
Ping : PDF Generation with Symfony2 – Part II: Zend Option | Craft It Online!
Bonjour
“Ne pas oublier de faire les imports des classes.”
Qels sont sont les classes a importer ???
Merci d’avance
Hmm, quand tu utilises une classe qui n’est pas dans ton namespace, il faut l’importer, stipuler où elle se trouve !
Je te conseil de trouver un tutoriel sur PHP 5.3, ou Java, ou un autre langage que tu apprécies. Si tu débutes, alors il faut d’abord que tu apprennes les bases avant de te lancer dans le code de symfony.
est-ce qu’il est vraiment nécessaire d’importer tout ZF dans son projet ??
Tu n’es pas obligé non, on utilise quelques classes
Apparemment le minimum à conserver c’est les deux dossiers :
vendor\Zend\library\Zend\Loader et vendor\Zend\library\Zend\Paginator
Petite info : les démarches montrées ici ne sont plus tt à fait valable (déjà knplabs doit partout être remplacé par knp maintenant). Pour avoir les nouvelles instructions => http://symfony2bundles.org/knplabs/KnpPaginatorBundle
Allez j’ai mis à jour l’installation et l’utilisation
sympa pour les prochains
Bonjour,
Peut-on ajouter des colonnes count, min, max, etc. à une requête qui utilise KnpPaginatorBundle, car j’ai essayé et cela ne fonctionne pas ?
Merci de votre réponse
Encore une petite question, en plus du sliding.html.twig dans le dossier app est-il possible d’avoir un sliding.html.twig utilisé uniquement dans un seul template et qui overide celui du dossier app ?? Merci!
et aussi comment passer d’autres paramètres que first, last, page… ? Pour utiliser comme filtre notamment ? Merci encore ^^
Pourquoi ne pas aussi installer via deps?
[Zend]
git=git://github.com/zendframework/zf2.git
target=/Zend