Pagerfanta

Documentation

Route Generator

Pagerfanta uses a route generator as a mechanism for building URLs to different pages in a paginated list.

A route generator is any callable which accepts a single $page parameter (the page to build the URL for) and returns the URL for the page being requested.

$routeGenerator = static fn (int $page): string => 'http://localhost/blog?page=' . $page;
Page number based route generators are deprecated since Pagerfanta 4.10. Use position route generators instead, which support both offset and cursor pagination. In Pagerfanta 5.0, a callable route generator will be given a position instead of a page number.

Generator Interface

It is recommended that route generators are classes which implement Pagerfanta\RouteGenerator\RouteGeneratorInterface.

The RouteGeneratorInterface is deprecated since Pagerfanta 4.10, implement the Pagerfanta\RouteGenerator\PositionRouteGeneratorInterface instead.

Generator Factory

Often, it is necessary to configure a route generator based on runtime information (such as data from the current request). The Pagerfanta\RouteGenerator\RouteGeneratorFactoryInterface defines a class which can assist in building your route generators.

The RouteGeneratorFactoryInterface is deprecated since Pagerfanta 4.10, implement the Pagerfanta\RouteGenerator\PositionRouteGeneratorFactoryInterface instead.

A basic example of how these factories can be used is with a Twig extension when rendering your pagination list.

<?php

namespace App\Twig;

use Pagerfanta\Pagerfanta;
use Pagerfanta\RouteGenerator\RouteGeneratorFactoryInterface;
use Pagerfanta\RouteGenerator\RouteGeneratorInterface;
use Pagerfanta\View\ViewFactoryInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

final class PagerfantaExtension extends AbstractExtension
{
    public function __construct(
        private readonly RouteGeneratorFactoryInterface $routeGeneratorFactory,
        private readonly ViewFactoryInterface $viewFactory,
    ) {
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('pagerfanta', $this->renderPagerfanta(...), ['is_safe' => ['html']]),
        ];
    }

    public function renderPagerfanta(Pagerfanta $pagerfanta, string $view, array $options = []): string
    {
        return $this->viewFactory->get($view)
            ->render($pagerfanta, $this->createRouteGenerator($options), $options);
    }

    private function createRouteGenerator(array $options = []): RouteGeneratorInterface
    {
        return $this->routeGeneratorFactory->create($options);
    }
}

Generator Decorator

Included in the core API is the Pagerfanta\RouteGenerator\RouteGeneratorDecorator class which can be used to decorate any route generator, whether the generator implements the interface or any callable.

The RouteGeneratorDecorator is deprecated since Pagerfanta 4.10, use the Pagerfanta\RouteGenerator\PositionRouteGeneratorDecorator instead.

The primary reason this class was created is to allow any generator to be used within Twig, but the decorator can also be used to enforce strict typehinting for generators.

When using the Twig view, it will automatically decorate any route generator so you will not need to do this on your own.

Position Route Generators

Position route generators were introduced in Pagerfanta 4.10.

A page number cannot describe a page of a cursor pager, so pagers describe the pages they link to with a Pagerfanta\Position\Position: either a Pagerfanta\Position\PagePosition (holding a page number) or a Pagerfanta\Position\CursorPosition (holding a cursor). A position route generator implements Pagerfanta\RouteGenerator\PositionRouteGeneratorInterface and builds the URL for a position.

Cursors should be converted to strings with a cursor encoder when building the URL. A route generator should throw a Pagerfanta\Exception\InvalidArgumentException for a position it does not support.

<?php

use Pagerfanta\Cursor\CursorEncoderInterface;
use Pagerfanta\Exception\InvalidArgumentException;
use Pagerfanta\Position\CursorPosition;
use Pagerfanta\Position\PagePosition;
use Pagerfanta\Position\Position;
use Pagerfanta\RouteGenerator\PositionRouteGeneratorInterface;

final class BlogRouteGenerator implements PositionRouteGeneratorInterface
{
    public function __construct(
        private readonly CursorEncoderInterface $cursorEncoder,
    ) {}

    public function __invoke(Position $position): string
    {
        return match (true) {
            $position instanceof PagePosition => 'http://localhost/blog?page=' . $position->page,
            $position instanceof CursorPosition => 'http://localhost/blog?cursor=' . $this->cursorEncoder->encode($position->cursor),
            default => throw new InvalidArgumentException(sprintf('Unsupported position "%s".', get_debug_type($position))),
        };
    }
}
In Pagerfanta 4.x, a plain callable given as a route generator is always treated as a page number based route generator. To use a callable as a position route generator, decorate it with the Pagerfanta\RouteGenerator\PositionRouteGeneratorDecorator class, which also provides a route() method for use in Twig templates.
<?php

use Pagerfanta\Position\Position;
use Pagerfanta\RouteGenerator\PositionRouteGeneratorDecorator;

$routeGenerator = new PositionRouteGeneratorDecorator(static fn (Position $position): string => /* ... */);

All of the views provided by Pagerfanta accept position route generators. The numbered views give the route generator a Pagerfanta\Position\PagePosition for each page they link to.

Position Route Generator Factory

Factories which can create position route generators implement Pagerfanta\RouteGenerator\PositionRouteGeneratorFactoryInterface.