Installation:
composer require data-dog/pager-bundle
Register the bundle in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 2/3):
return [
// ...
DataDog\PagerBundle\DataDogPagerBundle::class => ['all' => true],
];
First Use Case: Create a paginated Doctrine query in a controller:
use DataDog\PagerBundle\Pager\Pager;
use Doctrine\ORM\EntityManagerInterface;
public function index(EntityManagerInterface $em, Pager $pager)
{
$query = $em->createQueryBuilder()
->select('u')
->from('App\Entity\User', 'u');
$pager->setQuery($query);
$pager->setPage(1); // Default page
$pager->setItemsPerPage(10); // Default items per page
$users = $pager->getResults();
return $this->render('user/index.html.twig', ['users' => $users]);
}
Twig Integration:
Add the bundle’s Twig extensions to your config/packages/twig.yaml:
twig:
globals:
pager: '@data_dog_pager.twig.pager_extension'
Use in templates:
{% for user in users %}
{{ user.name }}
{% endfor %}
{{ pager.render() }} {# Renders pagination links #}
Query Setup:
Attach the Pager service to your controller/service and configure the base query:
$query = $em->createQueryBuilder()
->select('p')
->from('App\Entity\Project', 'p')
->where('p.status = :status')
->setParameter('status', 'active');
$pager->setQuery($query);
Dynamic Filtering:
Use addFilter() to bind request parameters to query conditions:
$pager->addFilter('name', 'LIKE', '%' . $request->query->get('name') . '%');
$pager->addFilter('status', '=', $request->query->get('status'));
Tip: Validate/sanitize input before passing to addFilter().
Sorting:
Enable sorting via addSort() with Twig integration:
$pager->addSort('createdAt', 'DESC', 'date'); // 'date' is the Twig template var
Render sortable headers in Twig:
<th>{{ pager.sort('createdAt', 'date') }}</th>
Pagination Links: Customize pagination output via Twig:
{{ pager.render({
'itemsPerPageOptions': [5, 10, 20],
'showItemsPerPage': true,
'showPageNumbers': true
}) }}
$pager->getResults() directly in JSON responses (e.g., with JsonResponse).$form = $this->createFormBuilder()
->add('name', TextType::class)
->getForm();
Then map form data to filters in the controller.$cacheKey = 'projects_' . md5($request->query->getString());
$users = $cache->get($cacheKey, function() use ($pager) {
return $pager->getResults();
});
Single Pagination Constraint:
The bundle enforces one pagination per request (via URL query params). Avoid mixing multiple pagers in the same request.
Workaround: Use separate routes or clear the pager state with $pager->reset().
Doctrine QueryBuilder Only:
The bundle exclusively supports Doctrine ORM QueryBuilder. Native queries or DQL strings will fail.
Fix: Use createQueryBuilder() even for simple queries.
Filter Injection Risks:
Directly passing user input to addFilter() can expose SQL injection. Always sanitize:
$name = $request->query->get('name', '');
$pager->addFilter('name', 'LIKE', '%' . addslashes($name) . '%');
Better: Use Doctrine’s ExpressionBuilder or parameterized queries.
Twig Extension Conflicts:
If pager.render() doesn’t work, ensure:
config/packages/twig.yaml.pager global variable.Query Dumping: Enable Doctrine debug mode to inspect the final query:
# config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
Check the generated SQL in the Symfony profiler.
Pager State: Dump the pager object to verify filters/sorts:
dump($pager->getQuery()->getDQL());
Custom Templates:
Override Twig templates in templates/DataDogPagerBundle/ (e.g., pagination.html.twig).
Example: Extend the pagination links to include icons:
{% extends 'DataDogPagerBundle:pagination.html.twig' %}
{% block page_link %}
<a href="{{ path('app_project_index', { _page: page }) }}" class="btn btn-outline-primary">
{{ page }}
</a>
{% endblock %}
Filter/Sort Logic:
Extend the DataDog\PagerBundle\Pager\Filter\AbstractFilter class to add custom logic (e.g., date ranges):
class DateRangeFilter extends AbstractFilter
{
public function apply(QueryBuilder $qb, $value)
{
$qb->andWhere('u.createdAt BETWEEN :start AND :end')
->setParameter('start', $value['start'])
->setParameter('end', $value['end']);
}
}
Register the filter in services.yaml:
services:
App\Pager\DateRangeFilter:
tags: { name: data_dog_pager.filter }
URL Generation:
Customize pagination URLs by overriding the getUrlGenerator() method in a custom pager service:
class CustomPager extends Pager
{
public function getUrlGenerator()
{
return function($page, array $params) {
return $this->router->generate('custom_route', [
'_page' => $page,
'filter' => $params['filter'] ?? null,
]);
};
}
}
10. Override globally in config/packages/data_dog_pager.yaml:
data_dog_pager:
items_per_page: 25
_page is not overridden by other route parameters. Use _pager_page as a fallback:
# config/routes.yaml
app_project_index:
path: /projects
defaults: { _controller: 'App\Controller\ProjectController::index' }
requirements:
_pager_page: \d*
How can I help you explore Laravel packages today?