Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Paginator class for symfony2 Give the possibility to create pagination on symfon2 and with bootstrap3, including Doctrine management
<?php
/*Controller/InvoiceController.php*/
namespace Ruby\CheckbookBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class InvoiceController extends Controller
{
public function listAction($page)
{
$maxPerPage = 20;
$itemQueryBuilder = $this->getEm()->getRepository('Concept:Invoice')
->createQueryBuilder('s')
->setParameter('fgsId', 10902);
//build object paginator
$paginator = $this->get('model.helper.paginator');
//instantiate all information for paginator
$paginator->applyOnQueryBuilder($maxPerPage, $itemQueryBuilder, 'ruby_checkbook_invoice_manager');
//items to display
$items = $itemQueryBuilder->getQuery()->getResult();
return $this->render('RubyCheckbookBundle:Invoice:list.html.twig', array(
'items' => $items,
'paginator' => $paginator
));
}
}
{#views/Invoice/list.html.twig#}
{% block body %}
<h1>Checkbook manager</h1>
<div class="container">
<table class="table table-bordered">
<thead>
<tr>
<th>id</th>
<th>Business date</th>
<th>Invoice date</th>
<th>Invoice</th>
<th>Supplier</th>
<th>Total account</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td>{{item.id}}</td>
<td>{{item.businessDate.format('Y-m-d')}}</td>
<td>{{item.invoiceDate.format('Y-m-d')}}</td>
<td>{{item.supplierInvoiceId}}</td>
<td>{{item.supplierId}}</td>
<td>{{item.invoiceAmount}}</td>
<td>new</td>
<td><a class="btn btn-primary" href='#'>Edit</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="center-block">
{% include "RubyCheckbookBundle:Invoice:pagination.html.twig" with { 'paginator' : paginator}%}
</div>
</div>
{% endblock %}
{#views/Invoice/pagination.html.twig#}
{% if paginator.maxPage > 1 %}
<ul class="pagination">
{% if paginator.currentPage > 1 %}
<li><a href="{{ path(paginator.paginationPath, paginator.currentFilters|merge({page: paginator.currentPage-1})) }}">&laquo; Previous</a></li>
{% else %}
<li class="disabled"><a>&laquo; Previous</a></li>
{% endif %}
{% for i in range(1, paginator.extremePagesLimit) if ( i < paginator.currentPage - paginator.nearbyPagesLimit ) %}
<li><a href="{{ path(paginator.paginationPath, paginator.currentFilters|merge({page: i})) }}">{{ i }}</a></li>
{% endfor %}
{% if paginator.extremePagesLimit + 1 < paginator.currentPage - paginator.nearbyPagesLimit %}
<li><a>...</a></li>
{% endif %}
{% for i in range(paginator.currentPage-paginator.nearbyPagesLimit, paginator.currentPage-1) if ( i > 0 ) %}
<li><a href="{{ path(paginator.paginationPath, paginator.currentFilters|merge({page: i})) }}">{{ i }}</a></li>
{% endfor %}
<li class="active"><a>{{ paginator.currentPage }}</a></li>
{% if paginator.currentPage < paginator.maxPage %}
{% for i in range(paginator.currentPage+1, paginator.maxPage) %}
{% if ( loop.index <= paginator.nearbyPagesLimit and i <= paginator.maxPage ) %}
<li><a href="{{ path(paginator.paginationPath, paginator.currentFilters|merge({page: i})) }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if (paginator.maxPage - paginator.extremePagesLimit) > (paginator.currentPage + paginator.nearbyPagesLimit ) %}
<li><a>...</a></li>
{% endif %}
{% for i in range(paginator.maxPage-paginator.extremePagesLimit+1, paginator.maxPage) if ( i > paginator.currentPage+paginator.nearbyPagesLimit ) %}
<li><a href="{{ path(paginator.paginationPath, paginator.currentFilters|merge({page: i})) }}">{{ i }}</a></li>
{% endfor %}
{% endif %}
{% if paginator.currentPage < paginator.maxPage %}
<li><a href="{{ path(paginator.paginationPath, paginator.currentFilters|merge({page: paginator.currentPage+1})) }}">Next &raquo;</a></li>
{% else %}
<li class="disabled"><a>Next &raquo;</a></li>
{% endif %}
</ul>
{% endif %}
<?php
/*Model/Helpers/paginator.php*/
namespace Ruby\CheckbookBundle\Model\Helpers;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\QueryBuilder;
/**
* Ruby\CheckbookBundle\Model\Helpers\Paginator
*/
class Paginator
{
//current displayed page
protected $currentPage;
//how many item in pagination on extreme side
protected $extremePagesLimit = 3;
//how many item in pagination on intern side
protected $nearbyPagesLimit = 2;
//route for link on view
protected $paginationPath;
//limit items on one page, default 10
protected $limitPerPage = 10;
//query builder used for counting and set offset and limit
protected $queryBuilder;
//oject request from symfony2
protected $request;
//how many items pulled by queryBuilder
protected $countItems;
//from countItems get number pages
protected $maxPage;
//information from request about all current parameter in url, used for link in view
protected $currentFilters;
public function __construct(Request $request)
{
$this->request = $request;
//by default will try to get page parameter
$page = $this->request->get('page');
if (isset($page)) {
$this->setCurrentPage($page);
} else {
$this->setCurrentPage(1);
}
$this->currentFilters = $request->query->all();
}
public function setCurrentPage($value)
{
$this->currentPage = $value;
return $this;
}
public function getCurrentPage()
{
return $this->currentPage;
}
protected function setLimitPerPage($value)
{
$value = intval($value);
if (empty($value)) {
$this->limitPerPage = 10;
} else {
$this->limitPerPage = $value;
}
return $this;
}
public function getLimitPerPage()
{
return $this->limitPerPage;
}
public function applyOnQueryBuilder($limitPerPage, $queryBuilder, $paginationPath, $extremePagesLimit = null, $nearbyPagesLimit = null)
{
$this->paginationPath = $paginationPath;
$this->extremePagesLimit = $extremePagesLimit ? $extremePagesLimit : $this->extremePagesLimit;
$this->nearbyPagesLimit = $nearbyPagesLimit ? $nearbyPagesLimit : $this->nearbyPagesLimit;
$this->setLimitPerPage($limitPerPage);
$this->queryBuilder = $queryBuilder;
$this->handlePageOutOfRange();
$this->countItems = $this->getCountItems();
$this->maxPage = $this->getMaxPage();
$this->queryBuilder->setFirstResult($this->getOffset())->setMaxResults($this->getLimitPerPage());
return $this;
}
protected function handlePageOutOfRange()
{
if ($this->currentPage > $this->getMaxPage() || $this->currentPage < 0 || empty($this->currentPage)) {
$this->currentPage = 1;
}
}
public function getCountItems()
{
if (!$this->countItems) {
return count($this->queryBuilder->getQuery()->getResult());
}
return $this->countItems;
}
public function getMaxPage()
{
if (!$this->maxPage) {
return ceil($this->getCountItems() / $this->limitPerPage);
}
return $this->maxPage;
}
public function getOffset()
{
return $this->limitPerPage * ($this->currentPage - 1);
}
public function getExtremePagesLimit()
{
return $this->extremePagesLimit;
}
public function getNearbyPagesLimit()
{
return $this->nearbyPagesLimit;
}
public function getPaginationPath()
{
return $this->paginationPath;
}
public function getCurrentFilters()
{
return $this->currentFilters;
}
}
#config/service.yml
services:
model.helper.paginator:
class: Ruby\CheckbookBundle\Model\Helpers\Paginator
arguments:
- "@request"
scope: request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.