Installation:
composer require datatheke/pager-bundle
Add the bundle to config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 2/3):
Datatheke\Bundle\PagerBundle\DatathekePagerBundle::class => ['all' => true],
Basic Usage (Doctrine ORM):
use Datatheke\Bundle\PagerBundle\Pager\DoctrineORMAdapter;
use Datatheke\Bundle\PagerBundle\Pager\PagerFactory;
$adapter = new DoctrineORMAdapter($entityManager->getRepository('App\Entity\User')->createQueryBuilder('u'));
$pager = PagerFactory::createPager($adapter, $request->query->all());
$pager->setItemsPerPage(10);
$pager->setCurrentPage($request->query->getInt('page', 1));
return $this->render('template.html.twig', [
'pager' => $pager,
]);
Twig Integration:
Use the pager Twig extension to render the grid:
{{ pager(pager, 'bootstrap3') }}
Controller:
public function listAction(Request $request)
{
$qb = $this->getDoctrine()->getRepository('App\Entity\User')->createQueryBuilder('u');
$adapter = new DoctrineORMAdapter($qb);
$pager = PagerFactory::createPager($adapter, $request->query->all());
return $this->render('user/list.html.twig', [
'pager' => $pager,
]);
}
Twig Template:
<table class="table table-striped">
{% for user in pager.items %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
</tr>
{% endfor %}
</table>
{{ pager(pager, 'bootstrap3') }}
Doctrine ORM:
$adapter = new DoctrineORMAdapter($qb);
$adapter->addSort('u.name', 'ASC'); // Sorting
$adapter->addFilter('u.active', '1'); // Filtering
Array Data:
$adapter = new ArrayAdapter($arrayData);
$adapter->setItemsPerPage(15);
MongoDB:
$adapter = new DoctrineMongoDBAdapter($mongoQueryBuilder);
DataTables (jQuery):
{{ pager(pager, 'datatables', {
'ajax': path('user_list_ajax'),
'columns': [
{ 'data': 'id' },
{ 'data': 'name' }
]
}) }}
Bootstrap 3 Theme:
{{ pager(pager, 'bootstrap3') }}
Pagination + Sorting + Filtering:
$pager = PagerFactory::createPager($adapter, $request->query->all());
$pager->setItemsPerPage(20);
$pager->setCurrentPage($request->query->getInt('page', 1));
AJAX Handling:
public function ajaxAction(Request $request)
{
$adapter = new DoctrineORMAdapter($qb);
$pager = PagerFactory::createPager($adapter, $request->query->all());
return $this->json($pager->getData());
}
Console Mode:
$adapter = new ArrayAdapter($data);
$pager = PagerFactory::createPager($adapter, [], PagerFactory::MODE_CONSOLE);
foreach ($pager as $item) {
print_r($item);
}
Customize Twig Extensions:
Override the pager Twig function in your theme by extending the bundle’s templates.
Reuse Adapters:
Create adapter services in services.yaml for dependency injection:
services:
App\Adapter\UserAdapter:
class: Datatheke\Bundle\PagerBundle\Pager\DoctrineORMAdapter
arguments: ['@doctrine.orm.entity_manager']
Event Listeners:
Use PagerEvents to modify behavior dynamically (e.g., pre-process filters):
$dispatcher->addListener(PagerEvents::PRE_FILTER, function ($event) {
$event->getAdapter()->addFilter('u.status', 'active');
});
QueryBuilder Modification:
QueryBuilder directly. Ensure your WHERE/ORDER BY clauses are added after the adapter’s logic if you need custom logic.Pagination Offsets:
setFirstResult()/setMaxResults(). For large datasets, ensure your database supports LIMIT/OFFSET efficiently.Twig Template Overrides:
@DatathekePager/pager.html.twig) to avoid missing variables.Console Mode Quirks:
MODE_CONSOLE) does not support all frontend handlers. Use array adapters for CLI tools.Check Adapter State:
dump($adapter->getQuery()->getSQL()); // Debug SQL
dump($adapter->getFilters()); // Inspect filters
Enable Profiler:
Use Symfony’s profiler to inspect the QueryBuilder state after adapter processing.
Handler-Specific Issues:
{
"data": [...],
"recordsTotal": 100,
"recordsFiltered": 50
}
Default Items Per Page:
Set globally in config/packages/datatheke_pager.yaml:
datatheke_pager:
default_items_per_page: 25
Theme Overrides:
Copy the theme templates from vendor/datatheke/pager-bundle/Resources/views/ to your project’s templates/ directory to customize without losing updates.
Handler-Specific Options:
Some handlers (e.g., datatables) require additional configuration. Refer to the handler documentation for specifics.
Custom Adapters:
Extend AbstractAdapter to support new data sources (e.g., Elasticsearch):
class ElasticsearchAdapter extends AbstractAdapter
{
public function __construct($client, $index) { ... }
public function applyFilters() { ... }
}
Custom Handlers:
Implement HandlerInterface for new frontend libraries:
class CustomHandler implements HandlerInterface
{
public function render(Pager $pager, array $options) { ... }
}
Event Subscribers:
Use PagerEvents to inject logic:
$dispatcher->addListener(PagerEvents::POST_BUILD, function ($event) {
$event->getPager()->setItemsPerPage(30);
});
Lazy Loading:
Use Pager::getIterator() for large datasets to avoid loading all items into memory.
Filter Optimization:
Apply filters early in the QueryBuilder to reduce the dataset size before pagination:
$qb->andWhere('u.active = :active')->setParameter('active', 1);
$adapter = new DoctrineORMAdapter($qb);
Caching:
Cache the QueryBuilder or adapter results if the underlying data rarely changes:
$adapter->setCache($cachePool);
How can I help you explore Laravel packages today?