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

Filtered Pagination Bundle Laravel Package

ns/filtered-pagination-bundle

Filtered Pagination Bundle adds filter-aware pagination to PHP applications, preserving query strings and active filters across page links. Generate paginated results that keep search, sort, and filter state intact, with simple integration and configurable templates.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check. This is a Symfony bundle, not a Laravel package. It has no Illuminate\Support\ServiceProvider, no Facade, no auto-discovery, and no config/filtered_pagination.php. If you composer require ns/filtered-pagination-bundle into a Laravel app you will get a package whose composer.json requires symfony/framework-bundle and whose service definitions are only loaded by Symfony's kernel. Laravel will happily install it and never boot it. Treat it as a reference implementation and a source of patterns, not a drop-in dependency.

Where to look first, in this order:

  1. composer.json — confirm the Symfony version constraint and which paginator it depends on (KnpPaginator, Pagerfanta, or its own). This tells you how much of the package is glue vs. logic.
  2. src/ — find the handler class. It is almost certainly a service that takes a Doctrine QueryBuilder, reads filters off the request, applies andWhere clauses, and hands the builder to a paginator.
  3. DependencyInjection/ and Resources/config/services.* — the service id and constructor arguments. In a Symfony host you'd confirm the id with bin/console debug:container | grep -i filter.
  4. README / tests — the whitelist format for filters is the real API surface.

Minimal Symfony usage (the only place this actually runs):

// bundles.php (Symfony 4+/Flex)
NobletSolutions\FilteredPaginationBundle\FilteredPaginationBundle::class => ['all' => true],

// Controller
public function index(Request $request, FilterHandler $handler): Response
{
    $qb = $this->getDoctrine()->getRepository(Order::class)->createQueryBuilder('o');
    $result = $handler->handle($qb, $request); // paginated result
    return $this->render('orders/index.html.twig', ['result' => $result]);
}

Your first Laravel use case is an admin listing — /admin/orders?status=paid&min_total=100&sort=-created_at&page=2 — where you want filtering and pagination without hand-writing thirty if ($request->filled(...)) blocks. Read the bundle's filter-application loop once, then build the equivalent in Laravel (see below). That is the fastest path to value from this package.

Implementation Patterns

Pattern 1 — Port the filter loop to Eloquent (recommended). The bundle's core is "whitelist of filter keys → closure that mutates a query builder." Express that as a Laravel pipeline:

class FilterPipeline
{
    public function __construct(private array $filters) {}

    public function apply(Builder $query, array $input): Builder
    {
        foreach ($this->filters as $key => $filter) {
            if (array_key_exists($key, $input) && $input[$key] !== null && $input[$key] !== '') {
                $filter($query, $input[$key]); // whitelisted closure
            }
        }
        return $query;
    }
}

Register per-model filter maps (OrderFilters, UserFilters) in a service provider and resolve them by model or route name. This preserves the bundle's separation of concerns without the Symfony baggage.

Pattern 2 — Symfony host with a Laravel-adjacent API layer. If your stack genuinely has a Symfony service (or you're migrating), use the handler in a controller and return JSON via a serializer. Keep the handler call in one thin controller action so the Symfony dependency stays at the edge and the rest of your domain code is portable.

Pattern 3 — Filter metadata endpoint. Expose the whitelist to your frontend so the UI can render the correct filter controls and validate client-side:

Route::get('/api/orders/filters', fn () => OrderFilters::schema());

The bundle's config-driven filter definitions map naturally onto this.

Pattern 4 — Sorting as a filter. Most naive implementations forget sorting. Model it as a separate whitelist (['created_at', 'total', 'status'] with a - prefix convention) rather than letting ?sort=anything reach orderBy(). The bundle typically handles pagination params only, so this is on you either way.

Workflow that works day to day:

  1. Define a filter class per resource with a filters() map and an allowedSorts() list.
  2. Validate the query string with a FormRequest (whitelist keys, cast types, cap page size).
  3. Pass validated data — never $request->all() — into the pipeline.
  4. Apply filters, then ->paginate($perPage)->withQueryString().
  5. Cache the filtered count for expensive listings; consider simplePaginate() for large tables.
  6. Feature-test with query strings and assert both the result set and the generated SQL bindings.

Gotchas and Tips

  • It will not boot in Laravel. No service provider, no config merge, no route publishing. Installing it and expecting app(FilterHandler::class) to work is the single most common dead end.
  • Doctrine, not Eloquent. The handler almost certainly expects a Doctrine\ORM\QueryBuilder. Passing an Eloquent builder will fail type checks. Even the query semantics differ (DQL vs. SQL, different join syntax, different null handling).
  • Request coupling. If the handler reads Symfony\Component\HttpFoundation\Request directly, you cannot reuse it from a queue job, console command, or API client. Extract parameters into an array/DTO first and treat request-parsing as a thin adapter.
  • Filter injection. Whitelisting is not optional. If filter keys map to column names or DQL fragments, an unvalidated ?filter[o.secret]=1 or a crafted sort value can leak columns or produce invalid queries. Validate against an explicit map and reject unknown keys.
  • Paginator type leakage. The return value may be a Knp/Pagerfanta object, which means your templates and JSON serializer become coupled to that library. Normalize to a plain array (items, page, per_page, total) at the boundary.
  • Count query cost. Filtered pagination runs an extra COUNT(*) on every request. On large, heavily-filtered tables this dominates latency. Profile it, cache it, or switch to simple pagination.
  • Debugging in Symfony: bin/console debug:container <id> to confirm the service is registered, debug:event-dispatcher if filters are applied via listeners, and log the final DQL/SQL. In Laravel's port, ->dd() the builder after all filters are applied, not before.
  • Extension points are narrow. Expect to override service definitions or add a compiler pass; there is unlikely to be a documented filter-interface you can implement cleanly. Forking is often simpler than fighting the config.
  • Maintenance risk is real. Four stars, zero dependents, a 0.02 score. Pin the exact version, vendor it if necessary, and wrap any behavior you rely on behind your own interface so you can swap it out. Write tests around the behavior you need (filtering + pagination), not around the package's internals — that way replacing it later costs you a day, not a sprint.
  • Best use of the repository: read it for its whitelist data structure and its "apply filters then paginate" composition, then delete it from composer.json.
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