Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Paginator Bundle Laravel Package

ttskch/paginator-bundle

A lightweight Symfony bundle for simple, flexible pagination. Turn Doctrine queries or arrays into paginated results with sortable pages, configurable page sizes, and Twig-friendly output for building list screens quickly.

View on GitHub
Deep Wiki
Context7

Getting Started

Framework reality check first: this is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no Blade views, and no composer require path into a Laravel app that doesn't drag in symfony/http-foundation, Twig, and Doctrine. As a Laravel developer, your day-to-day default remains Model::paginate() / LengthAwarePaginator. Read this package only if you're maintaining a Symfony app, auditing a dependency, or mining it for a clean pagination design to port.

If you are in a Symfony codebase, the whole API is three classes — read them before the docs, because that's genuinely all there is:

  1. src/Entity/Criteria.php — the request state (page, limit, sort key, direction).
  2. src/Paginator.php — paginate($target, $criteria): Slice.
  3. src/Entity/Slice.php (and its pages object) — what your template consumes.

Minimal wiring:

composer require ttskch/paginator-bundle
# config/packages/ttskch_paginator.yaml
ttskch_paginator:
    page_parameter_name: page
    sort_parameter_name: sort
    direction_parameter_name: direction
    default_sort_key: id
    default_direction: asc
    sortable_fields: [id, name, createdAt]
    limit: 10
    max_limit: 100
    template: '@TtskchPaginator/pagination.html.twig'
public function index(Request $request, Paginator $paginator, UserRepository $users): Response
{
    $criteria = new Criteria();          // hydrate page/sort/direction from $request->query
    $qb = $users->createQueryBuilder('u');

    return $this->render('user/index.html.twig', [
        'slice' => $paginator->paginate($qb, $criteria),
    ]);
}

First use case: a Doctrine-backed admin list with clickable column sorting. Confirm the exact Criteria hydration call against the README — the bundle is small enough that the source is more trustworthy than any tutorial.

Implementation Patterns

Target types drive everything. paginate() accepts a Doctrine QueryBuilder (count + limit/offset pushed to SQL), a plain array (sliced in memory), or a callable returning items plus a total. Pick by data size: arrays only for already-materialized small sets.

Whitelist sorting, always. sortable_fields is your SQL-injection and "sort by a column that doesn't exist" guard. Treat an empty list as a bug, not a default — decide explicitly whether that means "no sorting" or "unrestricted."

Criteria as a GET form. The clean pattern is a small form type bound to Criteria with method="GET", so filters, sort, and page all round-trip through the URL and the listing stays bookmarkable. On any filter or sort change, force page = 1 — otherwise the user lands on page 7 of a two-page result.

Template override, not template fork. Point template at your own Twig file and keep the bundle's expected slice contract. This is the intended customization seam and keeps you off the upgrade path.

Adapter if you're porting. If the goal is the design rather than the bundle, lift two ideas into Laravel: a Criteria value object hydrated from the request, and a Slice/Pages object rendered by a Blade component. That maps almost one-to-one onto LengthAwarePaginator plus ->appends($request->query()), and you keep Laravel's onEachSide, withQueryString(), and links().

Where it integrates. Symfony controllers, Twig templates, Doctrine repositories. There is no Livewire/Inertia equivalent, no JSON pagination resource, no API-mode response shape — you build the envelope yourself.

Gotchas and Tips

  • 11 stars, one maintainer, last release 2024-08-28. Vendor risk is the headline. Wrap it behind your own service so swapping it out is a one-file change, and pin the version.
  • max_limit silently clamps. If a request asks for limit=500 and max_limit is 100, you get 100 — and the page count changes underneath a user who bookmarked a deep page. Reflect the clamp in the UI, don't let it surprise people.
  • Doctrine count queries lie with joins. Classic paginator failure: a COUNT(*) over a query with JOIN/GROUP BY overcounts rows, and your last page is empty. If the slice has fewer items than expected on the final page, this is why — inspect the generated count SQL.
  • One count query per request. Pagination is inherently two queries. On large tables, cache the total for a short TTL or accept it; don't add SELECT COUNT to a hot path without measuring.
  • Parameter names are config, not convention. page, sort, direction are all renameable. If you're also running Laravel's ?page= anywhere nearby, or an API client assumes ?page[N], mismatches produce "always page 1" symptoms that look like a broken paginator.
  • No Laravel bundle registration equivalent. In Symfony you must add the bundle to config/bundles.php if Flex doesn't. In Laravel there is nothing to register because there is nothing to run.
  • Extension points are the operator/slicer layer. If your data source isn't Doctrine ORM or an array, that's where you plug in — but at 11 stars, expect to read the source to find the interface rather than find it documented.
  • Twig dependency is not optional in practice. The config default is a Twig template path; if you're rendering JSON, you're bypassing half the bundle and only using Slice.
  • Debugging tip: dump the Slice first, not the template. If current, last, total, and items|length disagree, the problem is the target/count, never the Twig.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle