symfony / ux-pagination
Cursor and numbered pagination for Symfony applications
Package info
github.com/symfony/ux-pagination
Type:symfony-bundle
pkg:composer/symfony/ux-pagination
Requires
- php: >=8.4
- symfony/config: ^7.4|^8.0
- symfony/dependency-injection: ^7.4|^8.0
- symfony/http-foundation: ^7.4|^8.0
- symfony/http-kernel: ^7.4|^8.0
- symfony/routing: ^7.4|^8.0
- symfony/translation-contracts: ^3.0
- symfony/twig-bundle: ^7.4|^8.0
- twig/twig: ^3.10.3
Requires (Dev)
- doctrine/dbal: ^4.4
- doctrine/orm: ^3.0
- phpstan/phpstan: ^2.1.17
- phpunit/phpunit: ^11.1|^12.0
- symfony/asset-mapper: ^7.4|^8.0
- symfony/browser-kit: ^7.4|^8.0
- symfony/css-selector: ^7.4|^8.0
- symfony/dom-crawler: ^7.4|^8.0
- symfony/framework-bundle: ^7.4|^8.0
- symfony/translation: ^7.4|^8.0
- symfony/ux-live-component: ^3.0
- symfony/ux-twig-component: ^3.0
Suggests
None
Provides
None
Conflicts
- doctrine/dbal: <4.4
- doctrine/orm: <3.0
- symfony/ux-live-component: <3.0
- symfony/ux-twig-component: <3.0
Replaces
None
This package is auto-updated.
Last update: 2026-09-03 07:02:01 UTC
README
EXPERIMENTAL This bundle is currently experimental and is likely to change, possibly significantly, before its first stable release.
Ship stable cursor feeds or classic numbered pages through one request-aware Symfony service. PHP owns the query, the built-in Twig themes render accessible navigation, and the browser follows ordinary links without requiring JavaScript.
Installation
composer require symfony/ux-pagination
Usage
// src/Controller/EventController.php namespace App\Controller; use App\Repository\EventRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; use Symfony\UX\Pagination\PaginatorInterface; final class EventController extends AbstractController { #[Route('/events', name: 'event_index')] public function __invoke( EventRepository $events, PaginatorInterface $paginator, ): Response { $pagination = $paginator ->cursor($events->createQueryBuilder('event')) ->orderBy(['createdAt', 'id'], 'DESC') ->perPage(20) ->paginate(); return $this->render('event/index.html.twig', [ 'pagination' => $pagination, ]); } }
{# templates/event/index.html.twig #} {% for event in pagination %} <article>{{ event.name }}</article> {% endfor %} {{ ux_pagination(pagination) }}
The paginator reads and validates ?cursor=, preserves the current filters and
generates previous/next URLs. Use query($source) for numbered pagination or
query($source)->lookahead() when the UI needs only previous/next without an
exact total. Use total($counter) when an aggregate query needs an
application-provided total; invokable Symfony services work directly.
What it provides
- First-class signed cursor pagination with forward and backward navigation
- Offset pagination with lazy totals and numbered pages
- Lookahead pagination without a count query
- Doctrine ORM 3 and DBAL 4.4+ adapters
- Callback builders and custom adapters for APIs, search engines and application sources
- Request-aware URLs generated through the Symfony Router
- Accessible, translated Twig navigation with Bootstrap, Tailwind and custom themes, plus validated attribute hooks
- Named paginator policies with Symfony autowiring
- PHP, Twig and JSON integration, plus LiveComponent support for numbered pages
- Real test helpers for page, URL and signed-cursor behavior
| Need | Strategy |
|---|---|
| Resist offset shifts while ordered values stay stable | Cursor |
| Page numbers and an exact total | Offset |
| Previous/next without a total | Lookahead |
Documentation
- Getting started
- Choosing a strategy
- Cursor pagination
- Rendering and customization
- Configuration
- Testing and debugging
Read the complete documentation in this repository.
This repository is a READ-ONLY subtree split.