Installation:
composer require arturdoruch/paginator-bundle
Register the bundle in AppKernel.php:
new ArturDoruch\PaginatorBundle\ArturDoruchPaginatorBundle(),
Basic Configuration (optional, defaults exist):
# app/config/config.yml
artur_doruch_paginator:
limit: 10
prev_page_label: '← Prev'
next_page_label: 'Next →'
First Use Case: In a controller, paginate a Doctrine ORM query:
use ArturDoruch\PaginatorBundle\Paginator;
public function indexAction($page = 1, Request $request)
{
$paginator = $this->get('arturdoruch_paginator');
$qb = $this->getDoctrine()->getRepository('AppBundle:Post')->createQueryBuilder('p');
$posts = $paginator->paginate($qb, $page, 10);
return $this->render('post/index.html.twig', ['posts' => $posts]);
}
Twig Integration: Use the provided Twig functions in your template:
{{ arturdoruch_pagination(posts.pagination) }}
$qb = $this->getDoctrine()->getRepository('AppBundle:User')->createQueryBuilder('u')
->where('u.active = :active')
->setParameter('active', true);
$users = $paginator->paginate($qb, $request->query->getInt('page', 1), 20);
$query = $qb->getQuery();
$users = $paginator->paginate($query, $page, 20);
$data = ['item1', 'item2', ..., 'item100'];
$paginatedData = $paginator->paginate($data, $page, 15);
$limit = $request->query->getInt('limit', 0); // 0 uses config default
$paginatedData = $paginator->paginate($query, $page, $limit);
$cursor = $this->getDoctrine()->getManager()->getConnection()->executeQuery('db.collection.find()');
$paginatedCursor = $paginator->paginate($cursor, $page, 10);
{% for page in arturdoruch_pagination_pages(posts.pagination) %}
<a href="{{ path('post_index', {'page': page}) }}">{{ page }}</a>
{% endfor %}
return new JsonResponse([
'data' => $posts,
'pagination' => [
'total_items' => $posts->getTotalItemCount(),
'current_page' => $posts->getCurrentPageNumber(),
'last_page' => $posts->getLastPageNumber(),
]
]);
{% macro paginationNav(pagination) %}
<nav>
{{ arturdoruch_pagination_prev(pagination) }}
{{ arturdoruch_pagination_next(pagination) }}
</nav>
{% endmacro %}
$page for negative values or non-integers. Sanitize in your controller:
$page = max(1, $request->query->getInt('page', 1));
toArray() before pagination.null for pagination metadata. Handle gracefully:
if (!$paginatedData) {
return $this->render('empty.html.twig');
}
// ❌ Bad: Modifies the original query
$qb->andWhere('...');
$paginator->paginate($qb, $page, 10);
// ✅ Good: Clone if needed
$clonedQb = clone $qb;
$paginator->paginate($clonedQb, $page, 10);
$posts->getTotalItemCount(); // Total items
$posts->getCurrentPageNumber(); // Current page
$posts->getLastPageNumber(); // Last page
$posts->getLimit(); // Items per page
# config.yml
doctrine:
dbal:
logging: true
-1 Limit$limit = -1 to fetch all items (bypasses pagination) for debugging:
$allItems = $paginator->paginate($query, 1, -1);
app/Resources/ArturDoruchPaginatorBundle/views/:
app/
Resources/
ArturDoruchPaginatorBundle/
views/
Pagination/
pagination.html.twig # Override default
Pagination class (e.g., add hasNextPage()):
// src/ArturDoruch/PaginatorBundle/Pagination.php
public function hasNextPage()
{
return $this->getCurrentPageNumber() < $this->getLastPageNumber();
}
artur_doruch_paginator:
prev_page_label: '« Anterior'
next_page_label: 'Siguiente »'
$form = $this->createFormBuilder()
->add('limit', ChoiceType::class, [
'choices' => [5, 10, 20, 50],
'data' => $request->query->getInt('limit', 10),
])
->getForm();
How can I help you explore Laravel packages today?