Key-set pagination for PHP

v1.2.2 2020-08-08 15:35 UTC

This package is auto-updated.

Last update: 2020-09-27 19:36:31 UTC


PagerWave is a pagination library for PHP.

It differs from most pagination libraries in that it uses key sets to keep track of the current location. Where traditional paginators use a page number to calculate an offset into your collection, PagerWave fetches n + 1 items when paging, then uses the n + 1th item to determine the starting point of the next page.

This difference is most obvious in the generated URLs. Offset-based paginators will give you a URL like /posts/1, while PagerWave will give you a URL like /posts/?next[date]=2020-04-20&[id]=455. While uglier, this has several performance and practical benefits compared to offset-based pagination:

  • The items on a page won't change as you add new items. This makes it ideal for infinite scroll scenarios, as adding or deleting items while someone is scrolling won't cause duplicate or skipped items, respectively.

  • It is fast with large databases, as key sets can take advantage of column indexes. Offset-based pagination, on the other hand, does not scale well as the database grows.

Currently, PagerWave has these drawbacks:

  • Backwards navigation is not supported.

  • Retrieving total item count is not supported.

  • Sorting by text might work, but is sketchy as the text would have to appear in the URL.

These may or may not be solved in the future.



use PagerWave\Definition;
use PagerWave\EntryReader\SimpleEntryReader;
use PagerWave\QueryReader\NativeQueryReader;
use PagerWave\Extension\DoctrineOrm\QueryBuilderAdapter;
use PagerWave\Paginator;
use PagerWave\UrlGenerator\NativeUrlGenerator;

$paginator = new Paginator(
    new SimpleEntryReader(),
    new NativeQueryReader(),
    new NativeUrlGenerator()

$queryBuilder = $em->createQueryBuilder()
    ->from(\App\Entity\Post::class, 'p');

$adapter = new QueryBuilderAdapter($queryBuilder);
$definition = new Definition(['rank' => 'DESC', 'id' => 'ASC']);

$cursor = $paginator->paginate($adapter, 100, $definition);

foreach ($cursor as $post) {
    printf("Title: %s (rank: %d)\n", $post->getTitle(), $post->getRank());

if ($cursor->hasNextPage()) {
    printf('<a href="%s">Show more</a>', $cursor->getNextPageUrl());

Supported paginatable collections

Supported HTTP abstractions


PagerWave is based on theory from Use the Index, Luke, and has taken inspiration from the Pagerfanta library.


This project is released under the Zlib licence.