cethyworks/doctrine-paginator-decorator
Installation:
composer require cethyworks/doctrine-paginator-decorator
Add to composer.json under require if not using autoload.
First Use Case:
Replace raw Doctrine Paginator with the decorator in a repository/service:
use Cethyworks\DoctrinePaginatorDecorator\DoctrinePaginatorDecorator;
$queryBuilder = $entityManager->createQueryBuilder()
->select('u')
->from('App\Entity\User', 'u');
$paginator = new DoctrinePaginatorDecorator($queryBuilder, $currentPage, $limitPerPage);
Key Methods to Explore:
getList() → Fetch paginated entities.getCount() → Get total records (avoids COUNT queries in some cases).hasNextPage() → Check for pagination bounds.Repository Layer:
Wrap Doctrine Paginator in a repository method:
public function paginateUsers(int $page, int $limit): array
{
$qb = $this->createQueryBuilder('u');
$paginator = new DoctrinePaginatorDecorator($qb, $page, $limit);
return [
'data' => $paginator->getList(),
'meta' => [
'total' => $paginator->getCount(),
'pages' => ceil($paginator->getCount() / $limit),
],
];
}
API Controller:
Use with Laravel’s Illuminate\Pagination\LengthAwarePaginator for consistency:
$items = $paginator->getList();
$total = $paginator->getCount();
return new LengthAwarePaginator(
$items,
$total,
$paginator->getLimit(),
$currentPage,
['path' => request()->url()]
);
Dynamic Query Building:
Chain QueryBuilder methods before passing to the decorator:
$qb = $this->createQueryBuilder('u')
->where('u.active = :active')
->setParameter('active', true);
$paginator = new DoctrinePaginatorDecorator($qb, $page, 10);
getCount() for Large Datasets: Use getTotalItemCount() from the underlying Paginator if the decorator’s getCount() triggers a full count query.Archived Package:
Method Overrides:
getCount() may not optimize like Doctrine’s native getTotalItemCount(). Verify with EXPLAIN in your DB.Pagination Edge Cases:
hasNextPage() returns false for empty pages, but getList() returns an empty array. Handle UI rendering accordingly.Query Inspection:
Use Doctrine’s QueryBuilder logging to verify generated SQL:
$qb->getQuery()->getSQL(); // Check the actual query
Decorator Internals:
If methods return unexpected results, inspect the underlying Paginator:
$paginator->getPaginator()->getIterator(); // Raw Doctrine Paginator
Custom Decorators:
Extend the class to add methods (e.g., getPreviousPageUrl()):
class CustomPaginator extends DoctrinePaginatorDecorator {
public function getPreviousPageUrl(): ?string
{
return $this->getPage() > 1
? route('users.index', ['page' => $this->getPage() - 1])
: null;
}
}
Laravel Integration:
Override the decorator’s getList() to return Laravel collections:
$paginator->getList()->map(fn($item) => new UserResource($item));
Configuration: No config file exists; pass all logic via constructor or dependency injection.
How can I help you explore Laravel packages today?