makerlabs/pager-bundle
PagerBundle brings flexible pagination to Symfony apps, with page and range pagers, adapters for Doctrine and arrays, and Twig helpers for rendering page links. Configure page size, window ranges and templates to build consistent paginated lists and search results.
Reality check before anything else. makerlabs/pager-bundle is a Symfony2 bundle, not a Laravel package. There is no ServiceProvider, no facade, no config/pager.php publish tag, and no Blade views. Its composer.json pins symfony/symfony: ~2.x era constraints that directly conflict with the Symfony 5/6/7 components Laravel 10/11 already install. You will not composer require this into a Laravel app — verify that in two commands rather than assuming it:
composer require makerlabs/pager-bundle --dry-run # expect a solver failure on symfony/*
composer why-not makerlabs/pager-bundle # shows the blocking symfony/* pins
If it happens to resolve (e.g. a very old Laravel 4/5 skeleton), it still won't boot: the bundle expects AppKernel registration and DependencyInjection/*Extension, neither of which exists in a Laravel kernel.
Where to look first, in order:
composer.json — PHP floor and symfony/* constraints. This one file decides whether the rest matters.DependencyInjection/Configuration.php — the real config tree: root key, page-size default, page-parameter name. This is the contract you'd copy if reimplementing.Pager / PagerInterface (the core class) — the page / perPage / total surface, offset calculation, and page-range logic. This is the only meat.Adapter/ (or equivalent) — array and Doctrine adapters. The array adapter is the pattern worth lifting.Resources/views/ — Twig partials. You will rewrite these as a Blade component, so skim for the class names and markup shape only.Your actual first use case is a port, not an install. In a Laravel app you already have Illuminate\Pagination\LengthAwarePaginator and CursorPaginator, which cover everything this package does — better and maintained. The package's only real value to you is as a read-only design reference: its separation of a Pager (math) from an Adapter (data source) from a view is a clean shape you can mirror in a small internal PagePresenter if you want consistent pagination UI across list views. Copy the idea, not the dependency.
Assuming you are porting the concept into a Laravel app (the only sensible path), these are the patterns the bundle implies mapped onto idiomatic Laravel:
Offset pagination (the bundle's core mode). The bundle computes offset = (page - 1) * perPage and totalPages = ceil(total / perPage). This is exactly what LengthAwarePaginator does. Use it directly — don't hand-roll:
$paginator = new LengthAwarePaginator(
$items, // slice for current page
$total, // total row count
$perPage,
$currentPage,
['path' => Paginator::resolveCurrentPath()]
);
When the data comes from Eloquent, just use ->paginate($perPage) and skip the manual construction entirely.
A shared page-range helper. The bundle computes a navigation window ("show 5 pages around current") — that's a genuinely useful, small piece of UI logic. Implement once as a Blade component or a PageRange helper so every list view renders the same way:
// e.g. app/Support/PageRange.php
class PageRange {
public static function window(int $current, int $total, int $radius = 2): array {
$start = max(1, $current - $radius);
$end = min($total, $current + $radius);
return range($start, $end);
}
}
Adapter pattern for non-Eloquent sources. The bundle's Adapter abstraction lets you paginate arrays, Doctrine results, or custom collections behind one interface. In Laravel the equivalent is a small interface you inject where you don't always have an Eloquent builder (search results from an API, in-memory collections, merged result sets):
interface PageSource {
public function total(): int;
public function slice(int $offset, int $limit): array;
}
Wire an Eloquent-backed and an array-backed implementation, then a single controller/trait can paginate either. This is the one piece of the bundle's architecture worth deliberately reproducing.
Consistent query-string handling. The bundle preserves the page parameter across links. Laravel does this via withQueryString() on the paginator. Call it whenever filters/sorts are active, otherwise filters silently drop on page 2 — a common bug.
Cursor pagination for hot tables. The bundle doesn't support this (offset only), but Laravel does via CursorPaginator. If you carry any of the package's "offset everything" habit into a high-volume table, deep pages will degrade linearly (LIMIT/OFFSET scans). Standardize: offset for admin lists, cursor for feeds/activity/large ordered tables.
Integration tip — keep the view layer a single component. One Blade component (<x-pagination :paginator="$paginator"/>) that accepts any Laravel paginator instance means swaps between LengthAwarePaginator and CursorPaginator are localized to that component, not scattered across views. This mirrors the bundle's separation and is a real long-term win.
Do not force the install. Running composer require ... --ignore-platform-reqs to bypass the Symfony constraint conflict turns a clean, honest rejection into a latent production fault. You'll get a bundle that boots in nothing and breaks in everything. If you truly need to read the code, git clone it into a throwaway directory, not vendor/.
Provenance mismatch — check before trusting the name. The package is makerlabs/pager-bundle but lives at smoya/PagerBundle. Confirm whether this is a fork, who holds Packagist publish rights, and whether the fork is patched relative to upstream. In a day-to-day Laravel context this likely won't matter because you won't install it — but if a transitive dependency ever pulls it in, you need to know which lineage you're getting.
Zero dependents means zero field-testing. There are no downstream bug reports, no compatibility matrix, no CVE surfacing through the usual channels, and a single maintainer. Any code you rely on from here, you own forever. Don't let "it looked simple" tempt you into vendor maintenance.
PHP version floor is a trap. The bundle targets PHP 5.x–7.x-era Symfony2. Under PHP 8.1+ (Laravel 10/11 baseline) you will hit deprecation fatals on first render — often not at install, but at the first page view in production. If you see this in a legacy context, that's the signal to migrate rather than patch.
Twig assumptions don't map to Blade. The bundle's Resources/views/ assumes Twig functions and Twig-specific helpers. Any ported template will need a from-scratch rewrite as Blade; don't try to translate line-by-line, design it against Laravel's $paginator->links() / Bootstrap/Tailwind views that ship with the framework.
Debugging tips for the port. When reimplementing offset math, the bugs cluster in two places: (1) page bounds — clamp to [1, totalPages] and test page=0 and page=totalPages+1; (2) empty sets — total=0 must yield one empty page, not totalPages=0 or a division-by-zero. The bundle's behavior on these edge cases is a useful reference even if you never install it.
Extension points worth knowing. The bundle's Adapter interface is where customization lives — its equivalents (custom data source, array adapter) are the patterns you'd copy. Its PagerInterface is where you'd swap offset for cursor math if extended. Both are instructive, neither is adoptable.
Config quirks. The bundle's DI Configuration.php defines defaults for page size and the page query parameter name. If you mimic this, define those defaults once in a config/pagination.php and read them everywhere (config('pagination.per_page')) — a single source of truth prevents the classic bug where one list view uses 15 and another 20.
Decision record. Log the finding ("rejected: Symfony2 bundle, 0/0, no Laravel surface") in your dependency registry with a re-evaluation trigger (a maintained Laravel port appears). That stops the next dev from re-opening the same dead end when the package name surfaces in a scan, and routes the real underlying need — consistent pagination UX — to your own backlog, where native Laravel primitives solve it in a day or two with no vendor exposure.
How can I help you explore Laravel packages today?