Pagination with Symfony 2 - Insane Visions

Pagination with Symfony 2

One of the many crucial parts of a content management system and websites that have an admin/engine/backend area, pagination, while often a simple feature – is needed if you plan to have more than a few items of data. Symfony 2 has a paginator class you can get separate, however it was overly complex and not easy to use for beginners. The following tutorial shows you the basics of getting a pagination up and running with your symfony 2 application.

The code is quite short and requires just a short amount of code lines in the controller action, routing and in the view to show the pagination, even better, the view is setup for use with bootstrap.

Controller Action Code

<?php
function indexAction(Request $request$offset 1)
{
    
$limit 10;
    
$from  = (($offset $limit) - $limit);
    
    
$em $this->getDoctrine()->getEntityManager();
    
    
$query     $em->getRepository('AppDefaultBundle:Default');
    
$entities  $query->createQueryBuilder('d');
    
$entities2 $query->createQueryBuilder('d');
    
    
$total_count $entities->select('COUNT(d)')->getQuery()->getSingleScalarResult();
    
    
$entities2->setFirstResult($from)->setMaxResults($limit);
    
$data $entities2->getQuery()->getResult();
    
    
$totalPages ceil($total_count $limit);
    
    return 
$this->render('AppDefaultBundle:Default:index.html.twig', array(
        
'data' => $data,
        
'totalPages' => $totalPages,
        
'page' => $offset
    
));
}

An offset is just another term for “page”, 10 is a basic limit set – of course this means 10 entries per page. Most of the rest is recognizable for those that are familiar with symfony. The main difference is that we are using two queries – one under $total_count, which does a quick query to get the total number of entries for this table – the result is returned as a string, by using “getSingleScalarResult()” and using a mysql COUNT.

For the other query, where we will actually get the entries to show – only for this page – we set a first result and max result. In this example, the first page would show entries 0-9 (10 including result #0). We then pass the totalPages variable which contains the total number of pages by dividing the max result amount by the amount of total entries.

Routing Entry

index_entries:
    pattern: /index/{offset}/
    defaults: { _controller: AppDefaultBundle:Default:index }

View File

{% if totalPages > 0 %}
    <div class=”pagination”>
        <ul>
 
        {% set prev = (page – 1) %}
        {% set next = (page + 1) %}
 
        {% if page > 1 %}
            <li><a href=”{{ path(‘default_page’, {  ‘offset’: prev }) }}”>«</a></li>
        {% else %}
            <li class=”active”><a>«</a></li>
        {% endif %}
 
        {% for i in range(1, totalPages) %}
            {% if page == i %}
                <li class=”active”><a>{{ i }}</a></li>
                {% else %}
                <li><a href=”{{ path(‘default_page’, {  ‘offset’: i }) }}”>{{ i }}</a></li>
                {% endif %}
 
                {% if i % 17 == 0 and i > 102 or i < 102 and i % 20 == 0 %}
 
                {% if page < totalPages %}
                    <li><a href=”{{ path(‘default_page’, {  ‘offset’: next }) }}”>»</a></li>
                {% else %}
                    <li class=”active”><a>»</a></li>
                {% endif %}
 
                </ul></div><div class=”pagination”><ul>
 
                {% if page > 1 %}
                    <li><a href=”{{ path(‘default_page’, {  ‘offset’: prev }) }}”>«</a></li>
                {% else %}
                    <li class=”active”><a>«</a></li>
                {% endif %}
            {% endif %}
        {% endfor %}
 
        {% if page < totalPages %}
            <li><a href=”{{ path(‘default_page’, {  ‘offset’: next }) }}”>»</a></li>
        {% else %}
            <li class=”active”><a>»</a></li>
        {% endif %}
 
    </ul>
    </div>
{% endif %}

We first check to see if there is even more than one page with the variable we passed in the controller action, if not, we show none of the pagination bar. Next up we need to set two variables with twig – the page number the “next” will lead to as well as “prev” for previous. If the current page is something more than just the first page, we show a nice back button and the opposite for the next page at the bottom.

Using twig’s nice “range” feature, we get to do a loop starting at 1 and ending with the last page. The rest is pretty self explanatory, but I do want to note for the code tidbit looking for a page number that is divisible by 17, bigger than 102, etc. – that has to do with bootstrap. As this code is setup to use the visual pagination style, I also came across a site with a huge database and that bit breaks up the pagination into numerous lines without stretching the page and looking ugly. 

Conclusion

This is another fairly simple symfony 2 tutorial, there were a few things left out such as the routing for “default_page”, however that leads to numerous things outside the scope of this tutorial. With very little modifying, you can use this code to paginate just about anything in symfony and without unecessary resource-intensive queries or having to mess with the pagination class. Any questions feel free to post. Enjoy!

James

Hi there, I'm James, editor in chief at InsaneVisions.com and finance journalist. Feel free to message me on Twitter and Facebook. Make sure to subscribe to our mailing visit for the latest finance and tech news.
James