Installation
composer require anh/paginator-bundle
Enable the bundle in config/bundles.php:
Anh\PaginatorBundle\AnhPaginatorBundle::class => ['all' => true],
Basic Usage
Register the paginator service in config/services.yaml:
anh_paginator:
class: Anh\Paginator\Paginator
arguments: ['@doctrine.orm.entity_manager']
First Use Case Paginate Doctrine results in a controller:
use Anh\PaginatorBundle\Paginator\Paginator;
class ProductController extends AbstractController
{
public function list(Paginator $paginator, int $page = 1)
{
$query = $this->getDoctrine()
->getRepository(Product::class)
->createQueryBuilder('p')
->getQuery();
$results = $paginator->paginate($query, $page, 10); // 10 items/page
return $this->render('product/list.html.twig', [
'results' => $results,
]);
}
}
Twig Integration
Use the paginator Twig extension for rendering:
{% for product in results %}
{{ product.name }}
{% endfor %}
{{ paginator(results) }}
Doctrine Pagination
$query = $entityManager->createQuery('SELECT u FROM App\Entity\User u');
$paginated = $paginator->paginate($query, $page, 20);
Custom QueryBuilder
$qb = $entityManager->getRepository(Product::class)
->createQueryBuilder('p')
->where('p.price > :min')
->setParameter('min', 10);
$results = $paginator->paginate($qb, $page, 15);
Dynamic Page Handling
$page = $request->query->getInt('page', 1);
$results = $paginator->paginate($query, $page, 10);
API Responses
$data = [
'data' => $results->getResults(),
'meta' => [
'page' => $results->getPage(),
'total_pages' => $results->getTotalPages(),
],
];
return $this->json($data);
Anh\PaginatorBundle\Form\Type\PaginatorType for form-based pagination.Anh\PaginatorBundle\Event\PaginatorEvent for pre/post-pagination logic.Anh\Paginator\Cache\CacheInterface if using Doctrine caching.templates/AnhPaginatorBundle/ for theming.Doctrine Version Mismatch
anh/paginator version constraints.anh/paginator:^0.2 and verify Doctrine integration in tests.Query Cloning Issues
QueryBuilder setups (e.g., custom DQL or HydrationMode) may break.->getQuery() directly instead of QueryBuilder.Pagination Links in Twig
path() or url(). For API routes, override templates or use paginator(results, {'route': 'api_product_list'}).Performance with Large Datasets
SET FIRST RESULT/SET MAX RESULTS, which can be slow for unoptimized queries.WHERE, ORDER BY).var_dump($results->getResults()); // Array of entities
var_dump($results->getTotalItems()); // Total count
# config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
Default Items per Page
Override in config/packages/anh_paginator.yaml:
anh_paginator:
items_per_page: 15 # Default for all paginators
Custom Paginator Class
Extend Anh\Paginator\Paginator and bind it as a service:
services:
App\Service\CustomPaginator:
class: App\Service\CustomPaginator
arguments: ['@doctrine.orm.entity_manager']
tags: ['anh_paginator.paginator']
Custom Paginator Adapter
Implement Anh\Paginator\Adapter\AdapterInterface for non-Doctrine data sources (e.g., Elasticsearch):
class ElasticAdapter implements AdapterInterface
{
public function getResults(QueryInterface $query, $offset, $limit)
{
// Custom logic
}
public function getTotalItems(QueryInterface $query)
{
// Custom logic
}
}
Event Subscribers
Listen to paginator.pre_paginate or paginator.post_paginate events:
use Anh\PaginatorBundle\Event\PaginatorEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MySubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
PaginatorEvent::PRE_PAGINATE => 'onPrePaginate',
PaginatorEvent::POST_PAGINATE => 'onPostPaginate',
];
}
public function onPrePaginate(PaginatorEvent $event)
{
$event->setItemsPerPage(30); // Modify dynamically
}
}
Twig Filters Extend Twig with custom filters for paginated data:
{{ results|custom_filter }}
// src/Twig/AppExtension.php
public function getFilters()
{
return [
new \Twig\TwigFilter('custom_filter', [$this, 'customFilter']),
];
}
How can I help you explore Laravel packages today?