Encore de la pagination, paginator de chez knplabs (et Zend!)

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/PaginatorBundle

Et 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 twig

templating 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 !

18 Réponses à Encore de la pagination, paginator de chez knplabs (et Zend!)

  1. cordoval dit :

    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,

  2. Ping : Symfony2 Paginator with Zend Git into Vendors! | Craft It Online!

  3. cordoval dit :

    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!

  4. keymaster dit :

    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.

  5. Ping : PDF Generation with Symfony2 – Part II: Zend Option | Craft It Online!

  6. drakuncorpkun dit :

    Bonjour
    “Ne pas oublier de faire les imports des classes.”

    Qels sont sont les classes a importer ???
    Merci d’avance

    • spike31 dit :

      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.

  7. Jedix dit :

    est-ce qu’il est vraiment nécessaire d’importer tout ZF dans son projet ??

  8. Jedix dit :

    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

  9. David dit :

    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

  10. Jedix dit :

    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!

  11. Jedix dit :

    et aussi comment passer d’autres paramètres que first, last, page… ? Pour utiliser comme filtre notamment ? Merci encore ^^

  12. Julien Ducro dit :

    Pourquoi ne pas aussi installer via deps?

    [Zend]
    git=git://github.com/zendframework/zf2.git
    target=/Zend

Répondre

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Twitter picture

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Connexion à %s

Suivre

Get every new post delivered to your Inbox.