Skip to content

Filtros ​

Los filtros añaden controles a la barra de filtros del listado, por encima de la búsqueda de texto libre. Se declaran dentro de filters():

php
public function filters(): array
{
    return [
        TernaryFilter::make('is_published')
            ->label('Status')
            ->trueLabel('Published')
            ->falseLabel('Draft'),

        SelectFilter::make('category')
            ->options(['news' => 'News', 'update' => 'Update', 'announcement' => 'Announcement']),

        DateRangeFilter::make('published_at')
            ->label('Published between'),
    ];
}

La clase base Filter ​

Todo filtro implementa type() (cómo se renderiza el control en el frontend) y apply(Builder $query, mixed $value): Builder (cómo se traduce el valor elegido en una cláusula de la query). El método label(string $label) es común a todos.

Para sobrescribir la lógica de matching de un filtro concreto sin crear una subclase nueva:

php
SelectFilter::make('category')
    ->options([...])
    ->query(fn (Builder $query, mixed $value): Builder => $query->where('category', $value)->whereNotNull('published_at'))

query() sustituye a apply() por completo cuando se proporciona.

Filtros incluidos ​

SelectFilter ​

Filtra por igualdad exacta sobre un desplegable de opciones.

php
SelectFilter::make('category')
    ->options(['news' => 'News', 'update' => 'Update', 'announcement' => 'Announcement'])

Internamente: $query->where($this->name, $value).

TernaryFilter ​

Tres estados: sí / no / cualquiera. Pensado para columnas booleanas.

php
TernaryFilter::make('is_published')
    ->trueLabel('Published')   // por defecto: "Yes"
    ->falseLabel('Draft')      // por defecto: "No"
    ->placeholder('Any status') // por defecto: "Any"

Acepta '1'/'true'/true como «sí» y '0'/'false'/false como «no»; cualquier otro valor no filtra nada.

DateRangeFilter ​

Un rango from/to sobre una columna de fecha.

php
DateRangeFilter::make('published_at')
    ->label('Published between')
    ->displayFormat('d/m/Y')

El valor esperado es un array ['from' => ..., 'to' => ...]; cualquiera de las dos claves es opcional, y cada una se traduce en un whereDate('>=', …) o whereDate('<=', …) independiente.

RelationFilter ​

Filtra el listado por un registro relacionado, elegido desde un combobox con búsqueda, el mismo componente que el campo Relation, pero como filtro.

php
RelationFilter::make('author_id')
    ->related(User::class)
    ->titleAttribute('name')
    ->optionsQuery(fn (Builder $query): Builder => $query->whereNotNull('email_verified_at'))
MétodoDescripción
related(class-string<Model> $model)El modelo relacionado.
titleAttribute(string $attribute)Atributo mostrado en cada opción. name por defecto.
searchColumns(string ...$columns)Columnas contra las que busca el combobox.
optionsQuery(Closure $callback)Restringe qué registros aparecen en el selector.
placeholder(string $text)Texto cuando no hay nada seleccionado. Any por defecto.

optionsQuery() y no query() deliberadamente: el Filter base ya tiene un query(Closure) heredado que sobrescribe cómo el filtro encaja los registros (véase «La clase base Filter» más arriba); reutilizar ese nombre para «qué opciones se ofrecen» colisionaría en silencio. RelationFilter sirve su propio endpoint de opciones, separado del de un campo Relation, precisamente porque un filtro y un campo pueden compartir el mismo nombre (filtrar por la misma columna que ya elige un campo del formulario).

Esta primera versión solo admite un único valor, todavía no hay una variante ->multiple().