Installation:
composer require efrag/paginator-bundle "~2"
Ensure your project uses Symfony 2.x/3.x (last release was 2019).
Enable the Bundle:
Add to app/AppKernel.php (Symfony 2/3) or config/bundles.php (Symfony 4+):
new Efrag\Bundle\PaginatorBundle\EfragPaginatorBundle(),
First Use Case:
Inject the efrag_paginator.paginator service into a controller and generate pagination for a query result:
use Efrag\Bundle\PaginatorBundle\Paginator\Paginator;
class MyController extends Controller
{
public function indexAction(Paginator $paginator, $page = 1)
{
$results = $this->getDoctrine()->getRepository('App:MyEntity')->findAll();
$pagination = $paginator->paginate($results, $page, 10, 'my_route_name');
return $this->render('template.html.twig', [
'pagination' => $pagination,
]);
}
}
Twig Integration: Use the provided Twig extension to render pagination links:
{{ pagination_links(pagination) }}
Pagination Generation:
Pass query results, current page, items per page, and route name to paginator->paginate():
$pagination = $paginator->paginate($results, $currentPage, $itemsPerPage, 'route_name');
$pagination = $paginator->paginate($results, 1, 10, 'route_name', ['filter' => 'value']);
Customizing Links:
Override the Twig template (@EfragPaginator/pagination_links.html.twig) or extend the Paginator service to modify link generation logic.
Dynamic Query Pagination: Use with Doctrine repositories or custom queries:
$query = $em->createQuery('SELECT u FROM App:User u WHERE u.active = :active')
->setParameter('active', true);
$pagination = $paginator->paginate($query->getResult(), $page, 10, 'user_list');
API Responses: Return pagination metadata as JSON:
return $this->json([
'data' => $results,
'pagination' => [
'current_page' => $pagination->getCurrentPage(),
'total_pages' => $pagination->getTotalPages(),
'total_items' => $pagination->getTotalItems(),
],
]);
Symfony\Component\Form\Extension\Core\Type\NumberType for page input:
$builder->add('page', NumberType::class, [
'attr' => ['min' => 1],
]);
paginate() method in AJAX calls to update content dynamically without full page reloads.$cacheKey = 'pagination_' . md5(serialize($results)) . '_' . $page;
$pagination = $cache->get($cacheKey, function() use ($paginator, $results, $page) {
return $paginator->paginate($results, $page, 10, 'route_name');
});
Route Name Sensitivity:
RuntimeException.php bin/console debug:router or use absolute URLs as a fallback (extend the service).Query Result Handling:
Traversable object. Doctrine QueryBuilder results must be fetched first (e.g., $query->getResult()).QueryBuilder directly will fail with:
Catchable Fatal Error: Object of class Doctrine\ORM\QueryBuilder could not be converted to string
$query->getResult() or $query->getScalarResult().Symfony 4+ Compatibility:
config/services.yaml:
services:
Efrag\Bundle\PaginatorBundle\Paginator\Paginator:
arguments:
$router: '@router'
Twig Extension Auto-Loading:
pagination_links Twig function isn’t recognized, ensure the bundle’s Twig extension is loaded. For Symfony 4+, add this to config/packages/twig.yaml:
twig:
paths: ['%kernel.project_dir%/vendor/efrag/paginator-bundle/Resources/views']
Check Pagination Data: Dump the pagination object to verify structure:
dump($pagination->getCurrentPage(), $pagination->getTotalPages(), $pagination->getItems());
Expected output:
array:3 [
"current_page" => int 1
"total_pages" => int 5
"items" => array:10 [ ... ]
]
Route Generation Issues:
$router = $this->get('router');
$url = $router->generate('route_name', ['page' => 2]);
page parameter (e.g., {page} in YAML routes).Performance:
setFirstResult()/setMaxResults() for database-level pagination:
$query->setFirstResult(($page - 1) * $itemsPerPage)
->setMaxResults($itemsPerPage);
$pagination = $paginator->paginate($query->getResult(), $page, $itemsPerPage, 'route_name');
Custom Pagination Class:
Extend Efrag\Bundle\PaginatorBundle\Paginator\Paginator to add methods (e.g., getPreviousPageUrl()):
class CustomPaginator extends Paginator
{
public function getPreviousPageUrl($route, $params = [])
{
$currentPage = $this->getCurrentPage();
if ($currentPage > 1) {
$params['page'] = $currentPage - 1;
return $this->router->generate($route, $params);
}
return null;
}
}
Register as a service in services.yaml:
services:
app.custom_paginator:
class: App\Service\CustomPaginator
arguments: ['@router']
public: true
Override Twig Templates:
Copy vendor/efrag/paginator-bundle/Resources/views/pagination_links.html.twig to templates/bundles/EfragPaginator/pagination_links.html.twig and customize:
{# Example: Add disabled state for current page #}
<li class="active">{{ pagination.getCurrentPage() }}</li>
Add CSS Classes:
Pass options to paginate() to customize link attributes:
$pagination = $paginator->paginate($results, 1, 10, 'route_name', [], [
'link_attr' => ['class' => 'pagination-link'],
'current_page_attr' => ['class' => 'active'],
]);
Update the Twig template to use these attributes.
Localization:
Override translation keys in config/packages/efrag_paginator.yaml:
efrag_paginator:
labels:
previous: '« Previous'
next: 'Next »'
How can I help you explore Laravel packages today?