?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:
order_by, it contains the defaults from Sort::asc(...) / Sort::desc(...) in the order you declared them.
4. Check a specific field
Sort|null. has() returns true if the field was declared on the route and is either defaulted or requested by the client.
Inside a resource
Resources exposeavailableSortings():
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.