Search by

silarhi / cursor-pagination

guillaume-sainthillier

A doctrine ORM cursor based pagination library for faster batch operations.

Package info

github.com/silarhi/cursor-pagination

pkg:composer/silarhi/cursor-pagination

Statistics

Installs: 38 445

Dependents: 0

Suggesters: 1

Stars: 3

Open Issues: 2

2.4.0 2026-10-14 09:01 UTC

README

Latest Stable Version Total Downloads License PHP Version CI Status Coverage

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 WHERE clause 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 maxPerPages items 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() and getNbPages(), with a plain COUNT when no join can duplicate rows.
  • Ready for doctrine/orm 4 — runs on Doctrine's CursorPaginator (doctrine/orm 3.7+), or its Paginator before 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:

Contributing

See CONTRIBUTING.md. Release notes are in CHANGELOG.md.

License

Released under the MIT License.