silarhi / cursor-pagination
A doctrine ORM cursor based pagination library for faster batch operations.
2.4.0
2026-10-14 09:01 UTC
Requires
- php: >=8.2
- doctrine/orm: ^3.0
Requires (Dev)
- doctrine/data-fixtures: ^2.2.1
- ergebnis/composer-normalize: ^2.54.0
- friendsofphp/php-cs-fixer: ^3.95.27
- phpstan/extension-installer: ^1.4.3
- phpstan/phpstan: ^2.3.1
- phpstan/phpstan-strict-rules: ^2.1.0
- phpunit/phpunit: ^11.5.57 || ^12.5.38 || ^13.4.1
- rector/rector: ^2.7.0
- symfony/cache: ^7.4.20 || ^8.0
- vimeo/psalm: ^5.26.1 || ^6.20.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 2.4.0
- 2.3.0
- 2.2.0
- 2.1.1
- 2.1.0
- 2.0.0
- 1.2.0
- 1.1.0
- 1.0.2
- 1.0.1
- 1.0.0
- dev-release/2.4.0
- dev-chore/pnpm
- dev-docs/changelog-2.4.0
- dev-release/2.3.0
- dev-docs/audit-fixes
- dev-feat/doctrine-orm-4-adapters
- dev-guillaume-sainthillier-patch-2
- dev-guillaume-sainthillier-patch-1
- dev-copilot/fix-000ead81-19c9-4efc-9460-7727982c8c58
This package is auto-updated.
Last update: 2026-10-14 09:03:29 UTC
README
Cursor Pagination
Cursor-based pagination for Doctrine ORM QueryBuilders.
Walk through large tables in fixed-size batches, without the cost of growing OFFSETs.
📖 Documentation
Features
- Keyset pagination — each page is fetched with a
WHEREclause built from the last row of the previous page. - Multi-field ordering — combine several fields, each ascending or descending, ending with a unique one.
- Item or chunk iteration — iterate entity by entity, or by arrays of
maxPerPagesitems for flush/clear batches. - Restartable iterations — every iteration starts from the beginning, even if a previous one was stopped early.
- Fetch joins handled — one query per page, or two when the query joins a collection or another entity (
JOIN … WITH): the page's ids, then their rows. - Query analysis — collection joins and scalar rows are detected; misconfigured orders throw instead of skipping rows.
- Counting —
count()andgetNbPages(), with a plainCOUNTwhen no join can duplicate rows. - Ready for doctrine/orm 4 — runs on Doctrine's
CursorPaginator(doctrine/orm 3.7+), or itsPaginatorbefore 3.7.
Requirements
PHP 8.2+ and doctrine/orm ^3.0.
Installation
composer require silarhi/cursor-pagination
Quick start
use Silarhi\CursorPagination\Configuration\OrderConfiguration; use Silarhi\CursorPagination\Configuration\OrderConfigurations; use Silarhi\CursorPagination\Pagination\CursorPagination; $queryBuilder = $entityManager->getRepository(User::class)->createQueryBuilder('u'); /** @var CursorPagination<User> $pagination */ $pagination = new CursorPagination($queryBuilder, new OrderConfigurations( new OrderConfiguration('u.createdAt', static fn (User $user): \DateTimeImmutable => $user->getCreatedAt()), new OrderConfiguration('u.id', static fn (User $user): int => $user->getId()), ), 100); foreach ($pagination->getChunkResults() as $users) { // up to 100 users per chunk $entityManager->flush(); $entityManager->clear(); }
Documentation
Everything else is on cursor-pagination.silarhi.dev:
- Installation and quick start
- How it works: keyset pagination against
OFFSET - Guides: ordering and unique keys, composite cursors, fetch joins and collections, scalar rows and memory, batch processing patterns
- Reference: CursorPagination, OrderConfiguration(s), ChunkIterator
Contributing
See CONTRIBUTING.md. Release notes are in CHANGELOG.md.
License
Released under the MIT License.