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 Filterable Laravel Package

n7olkachev/laravel-filterable

A lightweight Laravel package for filtering Eloquent models using request query parameters. Define allowed filters on your model, then let the package apply them automatically, keeping controllers clean and filter logic reusable.

View on GitHub
Deep Wiki
Context7

Getting Started

The headline of v2.0.0 is the new $filterable property, which exists to close the SQL-injection-style hole that open-ended filtering creates: letting a request name an arbitrary column is effectively letting the client shape your WHERE clause. Treat this release as a security-hardening upgrade, and budget time for it rather than dropping it in casually.

Minimal steps:

  1. composer require <vendor>/<package>:^2.0 and run your test suite before touching production code — the major bump signals behavioural change, not just an additive property.
  2. Open each model that is currently filtered from a request and look at it first. The $filterable declaration belongs there, next to $fillable, and should read like a deliberate contract rather than a copy of the table schema.
  3. Start with one read-only index endpoint. Declare the columns that endpoint genuinely needs to filter on, hit it with a known-good query string, and confirm the results match what you got on v1.
  4. Only then roll the property out across the rest of the models.

The first use case is almost always a paginated admin or API listing where the front end sends ?name=...&status=...&created_at=.... That is exactly the surface the new property protects, so it is the right place to validate the upgrade.

Implementation Patterns

Whitelist per model, not per application. Keep $filterable narrow and endpoint-driven. A User model exposing email for the support dashboard does not mean email should be filterable from the public API. If the package allows narrowing at call time, prefer declaring the full safe set on the model and further restricting it in the controller or a dedicated query object.

Pair it with your existing mass-assignment discipline. $fillable and $filterable answer different questions — what may be written versus what may be searched — but reviewers should see them side by side. If a column is sensitive enough to be excluded from $fillable, it is a strong candidate for exclusion from $filterable too.

Centralise filter parsing in a form request or query object. Validate and normalise incoming filter keys before they reach the package. This gives you a second gate in front of $filterable, produces clean 422s for unknown keys, and keeps controllers thin. A ListUsersQuery-style class that owns both the allowed keys and the eager-loading strategy scales much better than inline filtering.

Compose with pagination, sorting and scopes deliberately. Filter first, then sort, then paginate, and keep the ordering stable by always appending a tiebreaker column. When you add a scope that already constrains a column, make sure the same column being filterable does not let a caller widen the result set beyond the scope's intent.

Treat relationship filters as part of the whitelist. If the package supports filtering through relations, the $filterable entry is only half the story — the related model may also need its own declaration. Test nested filters explicitly, because this is where v2 upgrades tend to surprise people.

Write a test per declared column, plus one for a rejected column. A small dataset provider that asserts each whitelisted key works and that ?password=... or ?is_admin=1 is ignored or rejected is cheap insurance and documents the contract for the next developer.

Gotchas and Tips

This is a major version for a reason. The most likely breakage is that filtering on columns absent from $filterable now yields an empty result set or throws, where v1 happily filtered on anything. Audit your front end, your API clients and any saved bookmarks or dashboards that hard-code filter keys before deploying. Grep for query-string construction in your JS and for filter[ in your test fixtures.

An unset $filterable is not a neutral default. Decide explicitly whether the package fails closed (no filters allowed) or open (everything allowed) when the property is missing, and make that decision visible in your upgrade notes. If it fails closed, a forgotten model silently returns unfiltered listings — a bug that looks like a UI problem and wastes an afternoon. If it fails open, you have not actually gained the security benefit. Check the source or the changelog rather than assuming.

Do not reach for wildcards as a shortcut. If the package supports a catch-all entry, resist it. It reinstates exactly the vulnerability the release was written to fix, and it will pass code review because it looks tidy.

Debugging: log the resolved filter key set alongside the generated SQL (DB::listen or the query log) when a filter "does nothing". Distinguishing "key rejected by the whitelist" from "key accepted but matched no rows" is the single most common time sink with this class of package.

Config quirks: if a published config file controls the property name, the exception behaviour, or a global allow-list, publish it and commit it. A config default that differs between your local and production caches (config:cache) is a classic source of "works on my machine" filter failures.

Extension points worth knowing: custom filter resolvers or per-filter callbacks let you handle ranges, date boundaries and enum mapping without widening $filterable. Prefer adding a resolver for created_at over exposing raw column access, and prefer a scope for complex predicates over encoding logic in the request layer.

Rollout tip: ship $filterable declarations and the version bump in one PR, but enable the stricter behaviour behind a config flag if the package offers one. That gives you a fast rollback path if an overlooked client starts sending filters you have not whitelisted.

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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
adachsoft/php-code-style