Sorting
Server-side sort configuration and query payload
Sorting in ApiTables is always server-side. The frontend sends which column and direction; your Eloquent builder applies orderBy. The client cannot sort by columns you did not expose.
Defaults (when user has not sorted yet)
On every table class:
public string $defSortCol = 'id';
public string $defSortDir = 'desc';These appear in the load-table response. When query-table receives "sorts": [], the package uses these defaults.
Sortable columns
Only columns marked 'sortable' => true in $TBLColumns are included in the sortables array in structure JSON.
[
'type' => 'text',
'label' => 'email',
'data_src' => 'email',
'sortable' => true, // user can click column header to sort
],If sortable is omitted or false, the frontend should not offer sort for that column.
Query payload
{
"sorts": [
{ "field": "created_at", "direction": "desc" },
{ "field": "name", "direction": "asc" }
]
}| Field | Values |
|---|---|
field | Must be in sortables — usually matches data_src |
direction | asc or desc |
Multiple sorts are applied in order (secondary sort).
Relation columns
For 'data_src' => 'category.name', sort field in payload is typically category__name (double underscore), matching query result keys.
Ensure the join exists when sorting relation columns:
$this->builder = Product::query()
->leftJoin('categories', 'products.category_id', '=', 'categories.id')
->select('products.*');Senior: custom sort logic
Override sort application in your table class if you need computed sorts or case-insensitive ordering. The default behavior in TableAbstract maps field directly to orderBy on the builder.
Testing
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"page":1,"perPage":5,"sorts":[{"field":"name","direction":"asc"}],"filters":[]}' \
https://app.test/api/api-table/control-tables/query-table/usersVerify first item has lowest name alphabetically.