$request->filtering().
1. Declare filters on the route
::equals, ::in, ::like, ::contains, ::greaterThan, ::lessThan) binds a filter operator to a property. Not all filters support all operators — match them by type:
| Filter class | Operators |
|---|---|
StringFilter | equals, in, like, contains |
EnumFilter | equals, in |
IntegerFilter, FloatFilter, DateFilter, DateTimeFilter | equals, in, greaterThan, lessThan |
ByteFilter, BinaryFilter | equals, in |
BooleanFilter | equals |
2. Clients send filters in the query string
Two formats are supported — both work identically on the server. Flat — each filter is a top-level parameter:filter key:
FilterBag. If the same field is present in both (e.g. ?status=flat&filter[status]=bracket), the flat value wins.
RequestValidationMiddleware rejects anything you didn’t declare. Wrong type (age=not-an-integer) → 422. Unknown filter (?foo=bar where foo isn’t declared) is silently ignored.
3. Read values in the controller
$request->filtering() returns a FilterBag. Each filter exposes its operator via the isType*() methods and its value via getValue(), already cast to the correct PHP type.
$filters->has('name') returns false and $filters->name returns null — the bag is not populated with defaults for filters (unlike sorting).
4. Iterate when you want to apply them generically
Inside a resource
Resources exposeavailableFilters():
AbstractListResourceController wires them into the route for you — the controller reads from $request->filtering() exactly the same way. See the resource CRUD how-to.
OpenAPI side effects
Apivalk generates a singlefilter parameter of type object with style: deepObject. Each declared filter becomes a named property inside that object. Swagger UI renders each property as a separate input labelled filter[field] — matching the bracket notation clients should use. Both flat (?status=active) and bracket (?filter[status]=active) notation work at runtime; bracket is the documented canonical form.