monterhealth/api-filter-bundle
MonterHealth ApiFilterBundle adds request-driven filtering to Doctrine queries in Symfony APIs. Declare allowed filters on entities, map query parameters automatically, and keep controllers clean while supporting flexible, validated search endpoints.
First, the honest headline for a Laravel developer: this is a Symfony bundle, not a Laravel package. It targets Symfony's HTTP kernel, DI container, and (almost certainly) Doctrine ORM. There is no service provider, no facade, no config/api-filter.php. You cannot composer require it into a Laravel app and expect it to work. If you are evaluating it for a Laravel codebase, you are really evaluating the pattern it implements — declarative, whitelist-driven filtering and ordering of REST list endpoints — and deciding whether to port that pattern or adopt a native equivalent.
If you are in a Symfony project (or maintaining one alongside Laravel work), the minimal path is:
composer require monterhealth/api-filter-bundleconfig/bundles.php (Symfony Flex will usually do this).?filter[field]=value&order[field]=asc).GET /articles endpoint where the client can filter by a handful of whitelisted columns and sort by one or two. Wire it into a controller that hands a QueryBuilder to the bundle and returns the paginated result.For Laravel, the pragmatic equivalents to benchmark against are spatie/laravel-query-builder (closest in spirit), plain Eloquent local scopes, or a small custom middleware + query-object layer. Only port this bundle's classes if you specifically want its annotation-driven, entity-coupled style; otherwise you are reimplementing something Laravel already does more idiomatically.
The bundle's model is declarative whitelisting co-located with the model. You annotate (or attribute) entity properties as filterable/sortable, and the bundle translates incoming query parameters into query-builder constraints, ignoring anything not whitelisted. Day-to-day, that produces a few recurring patterns:
Request, obtains a QueryBuilder from a repository, applies the bundle's filter/order step, and paginates. Keep this in one place (a base controller or a thin service) so every list endpoint behaves identically.IN, date, and relation filters usually need explicit handling. The bundle's extension seam is where you add these rather than bolting logic into controllers.Mapping to Laravel if you port the idea: validate and normalize query params in a form request or a dedicated query object, resolve them against a whitelist array (ideally next to the model or in a Filterable concern), then apply Eloquent scopes. Keep the same separation — filter whitelist vs. sort whitelist — and return a typed result rather than mutating the builder in place in the controller. A base ListRequest + applyFilters(Builder $query) trait gets you 90% of this bundle's value in a few dozen lines.
QueryBuilder mean the classes are not drop-in portable to Laravel. If porting, take the design (declarative whitelists, request-to-query translation) and leave the implementations behind. MIT license makes this fine legally; the cost is engineering time.asc/desc), not a free string.How can I help you explore Laravel packages today?