Filters

Filter types, operators, and advanced filters

Filters let users narrow table results. You define them in PHP; the frontend renders a filter form from your definitions and sends the chosen values to query-table.

How filtering works (end to end)

  1. You return filter definitions from filters() on your table class
  2. load-table includes them in the filters array
  3. User fills the filter form in the UI
  4. Frontend POSTs filters: [{ field, operator, value }] to query-table
  5. TableAbstract::prepareQueryBuilder() applies each clause to the Eloquent builder

Junior takeaway

The filter_name you set in PHP must match the field the frontend sends. If users filter by name but nothing changes, check this match first.

Filter classes

Type keyClassTypical useOperators
textTextFilterName, email, search=, like
numberNumberFilterAmount, quantity=, !=, >, <, >=, <=, between
selectSelectFilterStatus, category=
multi_selectMultiSelectFilterMultiple statusesin
booleanBooleanFilterYes/no flags=
nullNullFilterIs null / not null=
dateDateFilterCreated at, due date=, comparisons, between
rangeRangeFilterNumeric/date rangesbetween

Examples

use Storageitsolutions\ApisTables\Filters\TextFilter;

public function filters(bool $api_array = true): array
{
    return [
        new TextFilter('name', 'name'),  // label, filter_name
    ];
}

Client sends:

{ "field": "name", "operator": "like", "value": "acme" }

Select dropdown

use Storageitsolutions\ApisTables\Filters\SelectFilter;

new SelectFilter('status', 'status', [
    'pending' => 'Pending',
    'active' => 'Active',
    'archived' => 'Archived',
]),

Third argument is value => label options shown in the UI.

Date range

use Storageitsolutions\ApisTables\Filters\DateFilter;

new DateFilter('created_at', 'created_at'),

Supports between for from/to date pickers.

Advanced filters

advancedFilters in structure JSON comes from filters(true) — same method, second call with $api_array = true. In most table classes both return the same array; override if you want a subset of filters only in the advanced panel.

Dynamic options (bindings)

Static dropdowns work for fixed enums. For DB-driven options:

protected function bindings(): array
{
    return [
        'category_id' => Category::pluck('name', 'id')
            ->map(fn ($name, $id) => ['value' => $id, 'label' => $name])
            ->values()
            ->toArray(),
    ];
}

Returned in query-table response under bindings.category_id so the frontend can populate selects without a separate API.

Filtering on relations

If filter_name targets a relation column, ensure the join exists in setInitialBuilder():

$this->builder = Order::query()->join('customers', ...);

Or use whereHas inside a custom filter callback (senior pattern via FiltersCallback trait).

Debugging checklist

IssueFix
Filter has no effectfieldfilter_name
Wrong operatorCheck allowed operators for filter type
Slow queriesAdd DB index on filtered columns
Empty dropdownImplement bindings() or pass select_options in SelectFilter

On this page