pagerfanta/doctrine-collections-adapter
Adapter connecting Pagerfanta pagination to Doctrine Collections. Paginate ArrayCollection and other Collection implementations with limit/offset slicing and count support, enabling easy integration of Doctrine collection data into Pagerfanta-based UIs.
Install Dependencies
composer require pagerfanta/pagerfanta pagerfanta/doctrine-collections-adapter
Ensure doctrine/collections is installed (automatically included via pagerfanta/doctrine-collections-adapter).
Basic Pagination Setup
use Pagerfanta\Pagerfanta;
use Pagerfanta\Adapter\DoctrineCollectionAdapter;
// Assume $doctrineCollection is a Doctrine\Common\Collections\Collection
$adapter = new DoctrineCollectionAdapter($doctrineCollection);
$pagerfanta = new Pagerfanta($adapter);
// Set pagination parameters
$pagerfanta->setMaxPerPage(20); // Items per page
$pagerfanta->setCurrentPage(1); // Current page
First Use Case: Paginating a Doctrine Repository Result
$entityManager = $this->getDoctrine()->getManager();
$users = $entityManager->getRepository(User::class)->findAll(); // Returns ArrayCollection
$adapter = new DoctrineCollectionAdapter($users);
$pagerfanta = new Pagerfanta($adapter);
// Get current page results
$currentPageUsers = $pagerfanta->getCurrentPageResults();
Controller Integration
public function index(Request $request)
{
$users = $this->userRepository->findAll();
$adapter = new DoctrineCollectionAdapter($users);
$pagerfanta = new Pagerfanta($adapter);
// Handle pagination parameters from request
$page = $request->query->getInt('page', 1);
$perPage = $request->query->getInt('per_page', 20);
$pagerfanta->setMaxPerPage($perPage);
$pagerfanta->setCurrentPage($page);
return view('users.index', [
'users' => $pagerfanta->getCurrentPageResults(),
'pagerfanta' => $pagerfanta,
]);
}
Service Layer Abstraction Create a dedicated service to encapsulate pagination logic:
class DoctrinePaginatorService
{
public function paginate(Collection $collection, int $page, int $perPage): Pagerfanta
{
$adapter = new DoctrineCollectionAdapter($collection);
$pagerfanta = new Pagerfanta($adapter);
$pagerfanta->setMaxPerPage($perPage);
$pagerfanta->setCurrentPage($page);
return $pagerfanta;
}
}
API Response Integration
public function apiUsers(Request $request)
{
$users = $this->userRepository->findAll();
$pagerfanta = $this->doctrinePaginator->paginate($users, $request->page, $request->per_page);
return response()->json([
'data' => $pagerfanta->getCurrentPageResults(),
'meta' => [
'total' => $pagerfanta->getNbResults(),
'pages' => $pagerfanta->getNbPages(),
'current_page' => $pagerfanta->getCurrentPage(),
],
]);
}
Leverage Pagerfanta’s Built-in Features
getLinks() for pagination links (supports Bootstrap, Twig, etc.):
$pagerfanta->getLinks('bootstrap_4');
$pagerfanta->getNbResults();
$pagerfanta->getNbPages();
Combine with Doctrine Criteria
$criteria = Criteria::create()
->where(Criteria::expr()->eq('status', 'active'))
->orderBy(['createdAt' => Criteria::DESC]);
$filteredCollection = $collection->matching($criteria);
$adapter = new DoctrineCollectionAdapter($filteredCollection);
Dependency Injection
Register the service in Laravel’s container (AppServiceProvider):
$this->app->bind(DoctrinePaginatorService::class, function ($app) {
return new DoctrinePaginatorService();
});
Form Request Validation
Validate pagination parameters in a FormRequest:
public function rules()
{
return [
'page' => 'integer|min:1',
'per_page' => 'integer|min:1|max:100',
];
}
Memory Usage
maxPerPage (e.g., 50–100 items) and avoid for large datasets (>10K items).QueryBuilder if possible:
$queryBuilder = $entityManager->createQueryBuilder();
$queryBuilder->select('u')
->from(User::class, 'u')
->setFirstResult(($page - 1) * $perPage)
->setMaxResults($perPage);
Empty Collections
OutOfRangeException if the collection is empty.if ($collection->isEmpty()) {
return response()->json(['data' => []]);
}
Page Number Validation
page=999) may cause errors.$maxPages = ceil($pagerfanta->getNbResults() / $pagerfanta->getMaxPerPage());
$pagerfanta->setCurrentPage(min($page, $maxPages));
Doctrine Version Mismatch
composer.json:
"require": {
"doctrine/collections": "^3.0",
"pagerfanta/doctrine-collections-adapter": "^1.0"
}
Lazy-Loading Quirks
$collection->matching($criteria)->toArray(); // Force load
Check Collection Structure
Use var_dump($collection->getIterator()->current()) to verify data integrity.
Log Pagerfanta Metadata
\Log::info('Pagination Meta', [
'total' => $pagerfanta->getNbResults(),
'pages' => $pagerfanta->getNbPages(),
'current' => $pagerfanta->getCurrentPage(),
]);
Memory Profiling Use Laravel Telescope or Xdebug to monitor memory usage during pagination.
Custom Adapter Logic
Extend DoctrineCollectionAdapter for custom behavior:
class CustomDoctrineCollectionAdapter extends DoctrineCollectionAdapter
{
public function getSlice($offset, $length)
{
// Custom logic for slicing
return parent::getSlice($offset, $length);
}
}
Integrate with Laravel’s Pagination Facade Create a facade to unify Pagerfanta and Laravel’s pagination:
Facades\Pagination::doctrine($collection, $page, $perPage);
Add Twig Extensions Register Pagerfanta helpers in Twig:
$twig->addFunction(new \Twig\TwigFunction('pagerfanta_links', function ($pagerfanta) {
return $pagerfanta->getLinks('bootstrap_4');
}));
Event Listeners Trigger events for pagination (e.g., logging, analytics):
$pagerfanta->addListener('postInitialize', function () {
\Log::info('Pagerfanta initialized');
});
Default Values
Pagerfanta defaults to maxPerPage=10 and currentPage=1. Override explicitly:
$pagerfanta->setMaxPerPage(25);
$pagerfanta->setCurrentPage($request->page ?? 1);
Case Sensitivity
Doctrine Collection methods (e.g., getIterator()) are case-sensitive. Ensure correct usage.
Thread Safety Pagerfanta instances are **not thread
How can I help you explore Laravel packages today?