Symfony 2 paginator – improved version

Symfony 2 paginator – improved version

NOTE: Tested on Symfony2 Beta3. Might not work on later releases!

After some comments on forums about my earlier post:
“Custom Pagination in Symfony 2” that was made on Symfony2 version: PR 12,
I decided to make some changes in the source code and give it available for download.

Basic structure of paginator is similar to latest post, but improvements are made by removing HTML stuff from controller, so paginator is rendered by twig template and not inside class on the fly.There are some more things that could be improved, for example:
I didn’t add some forward – backward arrow – links into displayed paginator and also didn’t limit number of links that will be shown, and I do not intend to.

If anybody thinks that it has to be improved more, fixed or something else, feel free to do it yourself.

Let’s show how to use it:

First, put class Paginator.php somewhere inside your Bundle. I put it into Helpers folder. Just rename namespace defined inside class to your own.

 * Paginator.php
 * Class to generate pagination for items
 * @author Darko Goleš
//Here replace namespace, depends where you put yours :
namespace Surgeworks\AdminBundle\Helpers;
class Paginator {

Before using it, just to take a look into the constructor for a moment:

    function __construct($itemscount, $currenturl, $options=array(10,20,30,50,100,500)) {
        //set total items count from controller
        $this->itemscount = $itemscount;
        //get params from request URL
        //Calculate number of pages total
        //Calculate first shown item on current page
        $this->currentUrl = $currenturl;
        $this->options = $options;

Why we looked into the constructor now? To see that there is third, optional argument that takes array of numbers with some predefined values. That is for: “how many items to show” list purpose.
In controller, when you use it, you can define custom values that will be shown in the select list (10, 20, 500). Also, you may not define ‘show All’ because that is already predefined in the twig template, so as this parameter, use only array of numbers.

Let’s take a look how to use it in the controller:

     * @extra:Route("/admin/languages", name="_admin_languages")
     * @extra:Template()
    public function indexAction() {
        //order of items from database
        $order_by = array();
        //get Entity manager instance
        $em = $this->get('doctrine.orm.entity_manager');
        //get repository for class 'Language' : LanguageRepository.php
        $repository = $em->getRepository('Surgeworks\AdminBundle\Entity\Language');
        //get count of languages for using with Paginator class
        //Using custom made database query function in LanguageRepository class
        $languagesCount = $repository->getLanguagesCount();
        //When creating new paginator object it takes care for pages and items
        //organization based on numbers of items from database and limit variable in $_GET
        $paginator = new Paginator($languagesCount, $this->generateUrl('_admin_languages'));
        //If we have POST variable defined, than it is defined order of items
        //from inside form (clicking on sorting column for example)
        if ('POST' === $this->get('request')->getMethod()) {
            $order_by = array($_POST['filter_order'] => $_POST['filter_order_Dir']);
            $sort_direction = $_POST['filter_order_Dir'] == 'asc' ? 'desc' : 'asc';
            $this->get('session')->set('lang_list_order_by', $order_by);
            $this->get('session')->set('lang_list_sort_dir', $sort_direction);
        } else {
            if ($this->get('session')->get('lang_list_order_by') != null) {
                $order_by = $this->get('session')->get('lang_list_order_by');
            } else {
                $order_by = array('sort_order' => 'asc', 'id' => 'asc');
            if ($this->get('session')->get('lang_list_sort_dir') != null) {
                $sort_direction = $this->get('session')->get('lang_list_sort_dir');
            } else {
                $sort_direction = 'desc';
        //To fill $languages for forwarding it to the template, we first call database function
        //with $offset and $limit to get items we wanted
        $languages = $repository->getLanguagesListWithPagination($order_by, $paginator->getOffset(), $paginator->getLimit());
        //Finally - return array to templating engine for displaying data.
        return array('languages' => $languages, 'sort_dir' => $sort_direction, 'paginator' => $paginator);

Of course, you need to make some function in LanguagesRepository to get count of items for paginator.

namespace Surgeworks\AdminBundle\Entity;
use Doctrine\ORM\EntityRepository;
class LanguageRepository extends EntityRepository {
    public function getLanguagesListWithPagination($order_by = array(), $offset = 0, $limit = 0) {
        //Create query builder for languages table
        $qb = $this->createQueryBuilder('l');
        //Show all if offset and limit not set, also show all when limit is 0
        if ((isset($offset)) && (isset($limit))) {
            if ($limit > 0) {
            //else we want to display all items on one page
        //Adding defined sorting parameters from variable into query
        foreach ($order_by as $key => $value) {
            $qb->add('orderBy', 'l.' . $key . ' ' . $value);
        //Get our query
        $q = $qb->getQuery();
        //Return result
        return $q->getResult();
    public function getLanguagesCount() {
        //Create query builder for languages table
        $qb = $this->createQueryBuilder('l');
        //Add Count expression to query
        $qb->add('select', $qb->expr()->count('l'));
        //Get our query
        $q = $qb->getQuery();
        //Return number of items
        return $q->getSingleScalarResult();

Don’t forget to add this repository class to Entity class:

namespace Surgeworks\AdminBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
 * @orm:Entity(repositoryClass="Surgeworks\AdminBundle\Entity\LanguageRepository")
 * @orm:Table(name="languages")
class Language{

After all of that is done, put paginator.html.twig inside Resources/views/Somewhere (I put in Resources/views/Global/ folder).
Let’s render it in twig template:

 {% include 'SurgeworksAdminBundle:Global:paginator.html.twig' %}

That’s all about paginator for now. Here you can download Symfony2 paginator files.

You made it all the way down here so you must have enjoyed this post! You may also like:

Symfony2 translating validator messages Darko Goles
Darko Goles, | 11

Symfony2 translating validator messages

TWIG with WordPress part1 Darko Goles
Darko Goles, | 1

TWIG with WordPress part1

Symfony2 Doctrine2 transactions Darko Goles
Darko Goles, | 10

Symfony2 Doctrine2 transactions

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.

Tell us about your project

Drop us a line. We'd love to know more about your project.