Skip to content

Instantly share code, notes, and snippets.

@cifren
Last active December 5, 2016 10:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cifren/7938081 to your computer and use it in GitHub Desktop.
Save cifren/7938081 to your computer and use it in GitHub Desktop.
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