Product Decisions This Supports
- API surface standardization. Filtering logic is a recurring cross-cutting concern across every list endpoint in a CRUD-heavy product. This package makes it a first-class, reusable primitive instead of copy-pasted
if ($request->has('status')) blocks scattered across controllers. That directly supports a roadmap decision to publish a consistent, documented set of query parameters across the public API.
- Build vs. buy for the filtering layer. The realistic alternative is 3–10 engineer-days of custom work (parser, whitelisting, type coercion, operator handling, validation errors) plus ongoing maintenance. This package shifts that to a dependency, which is the right trade if the filtering spec is generic and the team's differentiation is not in query parsing.
- Strategy-pattern extensibility as a roadmap hedge — now with evidence. Because filters resolve to strategies, adding new operators or domain-specific filters later is additive rather than a rewrite. v1.3.0 is a live demonstration: it added case-insensitive operators (
ilike, ieq, inoteq) as new strategies without touching the parsing or whitelisting contract. That is exactly the extensibility claim being tested, and it held. It lowers the cost of committing to a filtering contract now and expanding it in v2.
- Case-insensitive search as a product requirement, not just an operator. The v1.3.0 operators are the ones real users ask for ("search shouldn't care about capitalization"). Having them in the framework of record means case-insensitive matching becomes a documented API behavior with consistent semantics across endpoints, rather than whatever each team hand-rolls. It also has a second-order consequence worth flagging now:
ILIKE-style matching generally bypasses plain B-tree indexes, so this feeds directly into index-strategy and pagination-default decisions on high-traffic endpoints.
- Security posture as a product decision. Whitelisted, strategy-resolved filters materially reduce the risk of parameter-injection-style bugs and unbounded query cost on public endpoints — a decision that affects rate-limiting, pagination defaults, and abuse-handling workstreams. Note the operator surface is now wider (six-plus operators), so the whitelist is doing more work than it was at v1.2.1; keep it explicit rather than defaulting to "allow everything."
- Internal tools and admin/reporting endpoints. The highest-value first use cases are low-blast-radius: back-office dashboards, export endpoints, and internal APIs where flexible filtering saves analyst time. Case-insensitive matching is disproportionately valuable here (human-entered search terms, inconsistent casing in imported data).
- ⚠️ Framework mismatch is itself a decision input. Despite being filed here as a "Laravel/PHP package," the description and repository indicate a Symfony bundle. There is no Illuminate/Eloquent integration described, and v1.3.0 does nothing to change that. For a Laravel codebase, this is not an adopt — it is a read-and-port reference implementation, or a signal to evaluate
spatie/laravel-query-builder instead. Treat this as an architecture reference, not a dependency.
When to Consider This Package
Adopt (or evaluate seriously) when:
- The stack is Symfony with Doctrine ORM/DBAL query builders — the package's actual target.
- You have many list endpoints (roughly 5+) sharing overlapping filter semantics; below that, the integration overhead exceeds the payoff.
- You need whitelisted, validated filtering on an exposed API where unbounded query parameters are a real risk.
- Case-insensitive matching is a product requirement and you want it to be a documented, uniform behavior rather than a per-controller choice — v1.3.0 gives you
ilike, ieq, and inoteq out of the box.
- Your team already uses (or is comfortable with) strategy/resolver patterns and will extend the built-in strategies.
- Code is a viable long-term artifact for you: MIT license means you can fork and vendor it if the maintainer disappears.
Look elsewhere when:
- You are on Laravel. Eloquent is not addressed — still true as of v1.3.0. Either budget a port/adapter spike or use a Laravel-native package; do not assume compatibility from the "PHP" label.
- Filtering needs are simple and static — a handful of
where clauses, no operators, no composability. The abstraction cost outweighs the benefit.
- You need vendor accountability. 13 stars, zero dependents, and a single maintainer is a pre-adoption signal. v1.3.0 is a positive sign of life (two merged feature PRs, clean minor version, no breaking changes), but two PRs is not an SLA. If you require security review responses or CVE turnaround, this does not clear the bar.
- You need GraphQL, full-text search, or faceted aggregation. Query-builder filtering is the wrong layer; look at dedicated search infrastructure.
ilike is not a substitute for a search index — do not let it become one.
- You need multi-tenant/row-level authorization baked in. Filter whitelisting is not the same as access control — you will still need your own policy layer, and it is a common source of false confidence.
Adoption gate to set internally: a one-week spike porting or wiring two representative endpoints, plus a written exit plan (fork-and-vendor) since the maintenance risk is the dominant risk here. Re-baseline the spike against v1.3.0 so it exercises at least one case-insensitive operator against real data volumes and an existing index.
How to Pitch It (Stakeholders)
For executives: This is a small, MIT-licensed library that standardizes how our APIs accept filter parameters. It saves an estimated several engineer-days of bespoke work and, more importantly, eliminates a class of security and performance bugs caused by ad-hoc query parameter handling. The latest release (v1.3.0) adds case-insensitive matching — the behavior users expect from search — as a supported, consistent feature rather than something each team builds differently. Cost is near zero and the license permits us to take ownership of the code if we ever need to. The honest caveat is unchanged: it is a Symfony component with a very small community (13 stars, no known dependents), so for our Laravel services it is a design reference rather than a drop-in dependency — we would be adopting the pattern, not outsourcing the problem.
For engineering: The design is sound and conventional — HTTP request → filter resolution → strategy → query builder mutation, with whitelisting as the safety boundary. That is the right shape for the problem and worth copying regardless of whether we take the dependency. v1.3.0 validates the extensibility bet: new operators landed as additive strategies with no parser or whitelist changes and no breaking changes, so upgrading from v1.2.1 is low-risk. It also widens the operator surface, which means the whitelist now carries more weight and ILIKE-class operators need an index story (trigram or functional index, or accept the scan cost on small result sets). The decision to make: (a) if we are on Symfony/Doctrine, spike it on two endpoints including one case-insensitive filter, and vendor the source under MIT; (b) if we are on Laravel, do not integrate — implement the same strategy interface over Eloquent, or evaluate a maintained Laravel-native alternative. Either way we get a consistent filtering contract, explicit operator semantics, and a whitelist that is enforced in one place instead of in every controller.