Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.apivalk.com/llms.txt

Use this file to discover all available pages before exploring further.

For a walkthrough with client-side examples and resource integration, see the Add sorting how-to.

Route Configuration

To enable sorting for a specific route, you use the sorting() method on the Route object. This defines which fields can be used for sorting in the request.
use apivalk\apivalk\Router\Route\Sort\Sort;
use apivalk\apivalk\Router\Route\Route;

public static function getRoute(): Route
{
    return Route::get('/pets')
        ->sorting([
            new Sort('id'),
            new Sort('name'),
            new Sort('created_at'),
        ]);
}
By default, an Sort object just defines that a field is “sortable”.

Usage in Controller

When a route has sorting enabled, you can access the resolved sortings from the request via the sorting() method, which returns a SortBag. The bag is always populated for declared fields. If the client omits order_by, the bag holds the route’s defaults; if the client sends order_by, the requested sorts come first in iteration order, followed by any remaining defaults as tiebreakers.
public function __invoke(ApivalkRequestInterface $request): AbstractApivalkResponse
{
    $sorting = $request->sorting();

    // Iterate over all sortings (user-requested first, then route defaults).
    // Perfect for building an ORDER BY: the user's primary intent comes first.
    foreach ($sorting as $field => $sort) {
        $direction = $sort->isAsc() ? 'ASC' : 'DESC';
        // apply to your query...
    }

    // Or read a specific field directly via the magic getter.
    $direction = $sorting->name->isAsc() ? 'ASC' : 'DESC';

    // ...
}

Did the user pick this sort, or is it a default?

Each Sort knows whether it came from the user (?order_by=…) or from the route declaration. Use isRequested() when behavior should depend on user intent:
if ($sorting->status->isRequested()) {
    // The user explicitly asked to sort by status.
}
SortBag::getRequested() returns only the user-submitted sorts in the order they were sent — useful when you need user intent without route defaults mixed in:
foreach ($sorting->getRequested() as $sort) {
    // Only user-submitted sorts. Empty if the client did not send order_by.
}
has($field) only tells you whether the field is in the bag at all (which, for declared fields, is always true). To check whether the user requested a field, use isRequested() on the corresponding Sort.

Client-Side Usage

Apivalk supports sorting using the order_by query parameter. Clients can specify multiple fields and their sort direction using + (ascending, default) or - (descending) prefixes, separated by commas. Example: sort by name ascending and then by id descending GET /pets?order_by=name,-id

Validation

RequestValidationMiddleware rejects any sort field that isn’t declared in the route’s sorting([...]) list. A request like GET /pets?order_by=hacked_field returns 422 Unprocessable Entity with a validation error on the order_by parameter. Routes without any declared sortings skip this check entirely.

OpenAPI Documentation

When you configure sortings on a route, Apivalk automatically generates the corresponding OpenAPI documentation:
  • An order_by query parameter of type string.
  • The documentation describes the supported fields and the usage of +/- prefixes.