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

Laravel Filters Laravel Package

dcblogdev/laravel-filters

dcblogdev/laravel-filters provides a lightweight way to filter Laravel Eloquent queries from request parameters. Define allowed filters, apply them through a reusable trait, and keep controllers clean with composable, testable filtering logic.

View on GitHub
Deep Wiki
Context7

Getting Started

dcblogdev/laravel-filters is a small, focused package that turns request query strings into Eloquent query constraints, so you can drop hand-rolled $request->has('status') chains from your controllers.

  1. Install with Composer: composer require dcblogdev/laravel-filters. Package auto-discovery means there is normally no manual service-provider registration; check the README for any optional config/asset publishing step in the version you install.
  2. Read the README first — this is a deliberately tiny package, and the README is the authoritative source for the exact trait/class namespace and the signature of the filter entry point. Do not guess; confirm the trait name, whether filtering is exposed as a scope, a static call, or a dedicated filter class.
  3. Verify your platform. v2.0.3 adds explicit Laravel 13 support. Confirm your php and laravel/framework constraints are compatible before bumping, and run your test suite after the upgrade — the release itself contains only dependency bumps and no library code changes, so it should be a drop-in.
  4. First use case: an index listing. Take a route like GET /posts?status=published&sort=-created_at, apply the package's filter in the controller, and return the paginated result. That is the highest-value, lowest-risk place to start, because it replaces boilerplate you would otherwise write by hand in every controller.

A good rollout order: one read-only listing endpoint → feature tests covering representative query strings → then wider adoption across other index screens.

Implementation Patterns

Trait on the model, allowlist in the model. The healthiest pattern is to attach the package's filterable behaviour to the model and declare the columns that may be filtered alongside it. Keeping the allowlist on the model (or a dedicated filter class) rather than in the controller keeps the contract close to the schema and prevents controllers from drifting.

Thin controllers. The controller should only do three things: validate/authorise the request, hand the query string to the filter, and return the paginated result. All column mapping, sorting rules and default ordering belong in the model or filter definition.

// Controller shape — details depend on the package's API, confirm in README
public function index(Request $request)
{
    $posts = Post::filter($request->query())   // pseudo-API
        ->with('author')
        ->paginate(25)
        ->withQueryString();

    return view('posts.index', compact('posts'));
}

Pair it with Form Requests. Even though the package will ignore unknown keys, validating the shape of filter input (sort in an allowlist, status in an enum, dates parseable) gives you clean 422s and makes the frontend contract explicit. Validation and filtering are complementary, not redundant.

Sorting as a first-class citizen. Most real screens need ?sort=-created_at&sort=title. Decide early whether the package handles multi-column sort or whether you layer a small orderBy resolver on top; mixing both ad hoc is where listings start behaving inconsistently between screens.

Reuse across HTTP and non-HTTP callers. Because the filter is model-level, the same definition can back a JSON API controller, a Blade index view, and an internal report command. Pass an array of parameters rather than reaching for request() inside the model so the definition stays testable.

Test with real query strings. Feature tests of $this->get('/posts?status=published&sort=-created_at') catch the regressions that unit tests miss — unknown keys, empty values, arrays vs. scalars, and ordering.

Complement, don't duplicate. If you already use a larger filtering library, don't run both on the same model. Pick one owner of query-string → query-builder translation.

Gotchas and Tips

  • Never filter on unvalidated column names. The single biggest risk with any query-string filtering package is user input reaching an orderBy/where column position. Always constrain filterable and sortable columns to an explicit allowlist; the package cannot know your schema.
  • Empty and array values. ?status= and ?status[]=a&status[]=b are the classic breakage points. Confirm how your version handles empty strings (ignore vs. where status = '') and array input, and add a test for each.
  • Pagination links. Use withQueryString() on the paginator, otherwise page 2 silently drops the filters and looks like a package bug.
  • Unknown keys are usually ignored, not errored. If a filter "doesn't work", check the key spelling and the allowlist before digging into the package — silent no-ops are the most common false alarm.
  • Debugging: dump the resolved SQL with ->toSql() / ->getBindings(), or register a DB::listen() in a Tinker session. That tells you immediately whether the filter applied nothing, applied the wrong column, or applied correctly and the problem is elsewhere (e.g. a global scope or soft deletes).
  • Global scopes interact. Tenants, soft deletes and published-only global scopes apply before your filters; a filter that appears to be ignored is often being correctly narrowed by a scope above it.
  • About the v2.0.3 changes specifically: this release is dependabot bumps (symfony/http-foundation, league/commonmark, laravel/framework 10.48.29, phpunit 9.6.33, symfony/process, psy/psysh) plus Laravel 13 support. phpunit and psysh are dev-only and do not affect your runtime; the runtime-relevant bumps are transitive Symfony/Laravel constraints. No deprecations or breaking API changes are announced, so upgrading is low risk — but if you pin transitive versions or run Laravel 10 with a tight lockfile, composer update dcblogdev/laravel-filters -W and re-run tests rather than assuming.
  • Pin your constraint sensibly. ^2.0 is appropriate for a package at this maturity; avoid dev-main in production, since a dependency-only release like this one shows how little the maintainer surface area changes between tags.
  • Extension points to prefer over forking: wrap the filter in a base model or a small service class of your own so that if you outgrow the package (complex relationship filters, full-text search, faceted counts), you can swap the implementation without touching controllers.
  • Keep an eye on the changelog cadence. Releases here have been mostly maintenance. That is good for stability, but it also means new features are unlikely — evaluate it as "a small tool that solves query-string filtering," not as a query-builder framework.
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.
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
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console