Michael Emerson
Michael Emerson

Reputation: 1813

Doctrine pagination - restricting the number of pages shown?

Had a look at the documentation for this but could not find a definitive answer for what I need so not sure if it's possible but this is what I want to achieve:

I have a list of clients which is paginated in my Symfony2 project. There are currently a few hundred in the database but expected to grow. At the moment there are 22 pages of clients and the pagination I'm using is the standard Doctrine2 pagination. My function in my controller to show clients is as follows:

$em = $this->getDoctrine()->getManager();
$client_repo = $em->getRepository('AppBundle:Clients');
$clients = $client_repo->findByAccountStatus($status);
$message = false;
$page = $request->get('page');
$total_clients = count($clients);
$per_page = 20;
$total_pages = ceil($total_clients/$per_page);

if (!is_numeric($page)) {
    $page = 1;
} else {
    $page = floor($page);
}
if ($total_clients <= $per_page) {
    $page = 1;
}
if (($page * $per_page) > $total_clients) {
    $page = $total_pages;
}
$offset = 0;
if ($page > 1) {
    $offset = $per_page * ($page - 1);
}

$dql = "SELECT c FROM AppBundle:Clients c WHERE c.accountStatus = '".$status."'";
$query = $em->createQuery($dql)
    ->setFirstResult($offset)
    ->setMaxResults($per_page);

$paginator = new Paginator($query, $fetchJoinCollection = false);


return $this->render('AppBundle:tables:clientstable.html.twig', array(
    'clients' => $paginator,
    'total_pages' => $total_pages,
    'current_page' => $page
));

And my twig file implements the paging as follows:

{% if total_pages > 1 %}
<div class="text-center">
    <ul class="pagination">
        {% for i in 1..total_pages %}
            {% if loop.first %}
                <li class="prev{% if current_page==1 %} disabled{% endif %}"><a href="{% if current_page>1 %}{{ path('app_show_clients', {'page':current_page-1}) }}{% else %}javascript:void(0){% endif %}">«</a></li>
            {% endif %}
                <li{% if current_page==loop.index %} class="active"{% endif %}><a href="{{ path('app_show_clients', {'page':loop.index}) }}">{{ loop.index }}</a></li>
            {% if loop.last %}
                <li class="next{% if current_page == total_pages %} disabled{% endif %}"><a href="{% if current_page < total_pages %}{{ path('app_show_clients', {'page':current_page+1}) }}{% else %}javascript:void(0){% endif %}">»</a></li>
            {% endif %}
        {% endfor %}
    </ul>
</div>
{% endif %}

At the moment, the paginator shows all the pages, but in a couple of months when there may be double the amount of clients there are now, the number of pages will overflow on the screen and look messy. What I am wondering is, is there any way to restrict the number of pages shown at any one time in the pagination block so, for example, it shows 10 pages but as you click on a page it feeds more in, as an example:

[<<] [1] [2] [3] ... [20] [21] [22] [>>]

Then when you click page 3 it might look like this:

[<<] [3] [4] [5] ... [20] [21] [22] [>>]

or something like that?

Hope I'm explaining this well enough!

Michael

Upvotes: 0

Views: 728

Answers (2)

abdiel
abdiel

Reputation: 2106

Do not complicate yourself, use https://github.com/KnpLabs/KnpPaginatorBundle , is very easy to use and all the templates are configurable. Already integrated with bootstrap 2 and 3. If you prefer, you can use other, but this worked for me many times.

Upvotes: 1

scoolnico
scoolnico

Reputation: 3135

You have to add something like that in the view:

{% for p in range(max(current_page-3, 1), min(current_page+3, total_pages)) %}
    <a {% if p == current_page %} class="current-page"{% endif %} href="{{ path('route_name', {'page': p})) }}">{{ p }}</a>
{% endfor %}

Hope it will help you.

Upvotes: 1

Related Questions