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

Simple Paginator Bundle Laravel Package

ideup/simple-paginator-bundle

A lightweight Symfony bundle for adding simple, reusable pagination to your projects. It helps split Doctrine results or arrays into pages and render navigation controls, keeping templates clean and configuration minimal. A focused option for basic listing pages that don't need a heavier pagination...

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before any commands: this is a Symfony 2 bundle, not a Laravel package. composer require ideup/simple-paginator-bundle inside a Laravel app will try to pull Symfony 2 components and collide with your framework. There is no service provider, no facade, no config/paginator.php. For a Laravel developer, "day-to-day leverage" means reading ~200–300 lines of source and porting the slice-and-count pattern into your own code — not adding a dependency.

Reading order (an hour, once):

  1. Resources/config/services.yml — the service id (typically ideup.simple_paginator) and the class it wires. That class is the entire public API.
  2. The Paginator value object — look for getItems(), getPage(), getTotalItems(), getTotalPages(), hasNextPage(), getNextPage(). These are the methods your port must replicate.
  3. Resources/views/ — the shipped Twig template showing exactly which variables the pager expects.
  4. Tests/ — for an unmaintained bundle, tests are the most accurate docs.

First use case (the canonical Symfony 2 flow):

public function indexAction(Request $request)
{
    $qb = $this->getDoctrine()->getRepository('AcmeDemoBundle:Post')
        ->createQueryBuilder('p')
        ->where('p.published = :published')
        ->setParameter('published', true)
        ->orderBy('p.createdAt', 'DESC');

    $page   = max(1, (int) $request->query->get('page', 1));
    $result = $this->get('ideup.simple_paginator')->paginate($qb, $page, 20);

    return $this->render('AcmeDemoBundle:Post:index.html.twig', array(
        'items'     => $result->getItems(),
        'paginator' => $result,
    ));
}

First use case (what you would actually do in Laravel): reimplement that method over Illuminate\Database. One service class, one method, no dependency:

class PaginateQuery
{
    public function __invoke($query, int $page = 1, int $perPage = 20): PaginatedResult
    {
        $page = max(1, $page);
        $total = (clone $query)->count();
        $items = $query->forPage($page, $perPage)->get();

        return new PaginatedResult($items, $total, $page, $perPage);
    }
}

Implementation Patterns

Symfony 2 controller pattern. Inject the paginator service, pass a Doctrine QueryBuilder (or Query, or a plain array) plus page and page size. The bundle slices the result and returns a value object carrying items, current page, and page count. Keep controllers thin — pass the query builder, not a hydrated collection, so the count stays cheap.

Array pagination. The bundle also accepts plain arrays, useful for aggregating non-DB data before paging. In a port, collect($items)->forPage($page, $perPage) is the direct equivalent.

Configuration-driven page size and param name. Page size and the query parameter name (page by default) are configurable through the bundle's DI tree. Don't hardcode $_GET['page'] in templates — read the paginator's own getPage() so the link builder stays consistent.

Pagination behind an interface (the pattern worth stealing). Whichever stack you're on, do not let the paginator leak into application/domain code. Define your own contract and adapt:

interface PaginatesResults
{
    public function paginate($query, int $page, int $perPage): PaginatedResult;
}

Then the Symfony bundle is one implementation, your Eloquent version is another, and swapping is a container binding — the real payoff for a package with zero dependents and a dead framework target.

Blade/template rendering. The shipped Twig template is disposable — copy the shape (previous, windowed page numbers, next), not the file. In Blade:

@foreach ($paginator->window() as $n)
    <a href="{{ request()->fullUrlWithQuery(['page' => $n]) }}"
       class="{{ $n === $paginator->currentPage() ? 'active' : '' }}">{{ $n }}</a>
@endforeach

Use fullUrlWithQuery() so filters/search survive page changes — a bug the 2013-era template won't guard against.

Porting to Eloquent. Replace Doctrine query decoration with Illuminate\Database equivalents: clone the query before count() (Eloquent builders are mutable and count() can strip select/orderBy assumptions), then forPage($page, $perPage)->get(). Keep the returned value object's method names close to the original to preserve mental mapping during migration.

Integration tips. Wrap the count in a cache for expensive filtered queries. Prefer the native Illuminate\Pagination for anything new — it already provides length-aware pagination, cursor pagination, and Blade views; the only reason to hand-roll is reproducing a specific pager UX.

Gotchas and Tips

  • Naming drift. getItems() vs getResult() exists across versions of this bundle. Don't write blind against a tutorial; check the actual class in services.yml's target first.
  • Page clamping is on you. The bundle expects a sane page; passing 0 or negatives produces a bad offset. Always max(1, (int) $request->query->get('page', 1)) before calling, and clamp to the last page in your result object to avoid empty "page 99" screens.
  • 1-indexed pages. The API is one-based throughout; mix it with a zero-based offset() by hand and you get off-by-one bugs that only show on the last page. Centralise the conversion in the result object.
  • COUNT(*) cost. Naive total counting dominates response time on large filtered tables. Cache it per filter set, or skip total-based pagination for large datasets — the bundle has no concept of "length unaware" paging.
  • Deep OFFSET degradation. Offset paging skips rows under concurrent writes and slows at high page numbers. For big/fast-changing tables, the right answer is keyset pagination — a capability this bundle does not offer, which is itself a reason to use the native Laravel paginator instead of porting it.
  • QueryBuilder mutation (Doctrine). The bundle may mutate the builder it's handed. Clone before paging if you reuse the query elsewhere. Same caution applies to Eloquent's mutable builders in a port.
  • PHP 8 / modern framework incompatibility. Assume deprecation or fatal errors under PHP 8.x and zero Symfony 3+ support. Run static analysis before committing to any Symfony-side revival; expect a compatibility pass as the first task.
  • No Laravel service provider exists. Don't add a facade and expect it to resolve — there's nothing to bind. If you fork, the service provider is work you write and own.
  • Zero dependents = no backstop. No issue triage, no security patch path, no community answers. Log it as a technology-debt item with a named owner if you vendor it, and set a deprecation trigger tied to your framework upgrade.
  • Extension points are thin. There's no event system worth relying on; customisation means subclassing the paginator service or overriding the Twig template in your bundle — the latter is the only genuinely low-friction hook. If you need more, that's a signal to build your own rather than extend this one.
  • Debugging tip. When output looks wrong, dump the raw count and offset before suspecting the pager: var_dump($page, $perPage, ($page - 1) * $perPage, $total). Nine times out of ten the arithmetic at the call site, not the bundle, is the bug.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core