Sorting is route-level. You declare which fields the endpoint will sort by (and their default direction); clients send ?order_by=... to override it; the framework parses, validates, and populates $request->sorting() for you.
1. Declare sortable fields
Sort::asc('name') means: “sortable on name; if the client doesn’t override, default direction is ascending”. Sort::desc(...) is the reverse.
2. Clients pass order_by
The format is a comma-separated list of field names, each optionally prefixed with + (ascending, default) or - (descending):
RequestValidationMiddleware rejects anything not declared — ?order_by=hacked_field → 422. Routes without sorting([...]) skip this check entirely (nothing to validate against).
3. Read the resolved sorts
$request->sorting() returns a SortBag. It implements IteratorAggregate, so iterate directly:
The bag is always populated — if the client omits order_by, it contains the defaults from Sort::asc(...) / Sort::desc(...) in the order you declared them.
Iteration order matches user intent: any sorts the client submitted via ?order_by= come first (in submission order), followed by the route’s defaults for fields the client didn’t specify. So foreach produces the right ORDER BY sequence — primary user choice first, defaults as tiebreakers — without you having to merge anything.
4. Tell user-requested sorts from defaults
Each Sort knows whether it came from ?order_by= or from the route declaration. Branch on isRequested() when you need to:
To get only the user’s submitted sorts (without route defaults), use getRequested():
has($field) only tells you whether the field is in the bag at all — for declared fields, that’s always true because defaults seed the bag. Use isRequested() to ask “did the user ask for this?”.
Inside a resource
Resources expose availableSortings():
AbstractListResourceController reads this and calls $route->sorting([...]) for you. The DocBlock generator also emits typed @method annotations on *ListRequest so $request->sorting()->name autocompletes. See generate OpenAPI + docblocks.
OpenAPI side effects
One query parameter — order_by — is added to the operation with:
type: string
- Description listing supported fields and the
+ / - syntax.
- Example matching your declared defaults.
Reference
Full behaviour and edge cases live at HTTP / Sorting.