跳到主要内容
版本:2.x

过滤器

开始

过滤器(Filters)让你可以以某种方式筛选 Eloquent 查询的数据,减少表格中的记录数。

如果你在 Livewire 组件中使用过滤器,请将其放在 getTableFilters() 方法中:

protected function getTableFilters(): array
{
return [
// ...
];
}

如果你在后台面板的资源或者关系管理器中使用,将它们放在 $table->filters() 方法中:

public static function table(Table $table): Table
{
return $table
->filters([
// ...
]);
}

过滤器使用静态方法 make() 并传入过滤器名称创建。过滤器名称应该是唯一的。然后你应该传一个回调函数作为参数到 query() 方法中,该回调函数使用过滤器的查询范围:

use Filament\Tables\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;

Filter::make('is_featured')
->query(fn (Builder $query): Builder => $query->where('is_featured', true))

设置标签

默认情况下,显示在过滤器表单中的过滤器标签,是由过滤器名生成。你可以使用 label() 标签自定义:

use Filament\Tables\Filters\Filter;

Filter::make('is_featured')->label('Featured')

此外,你也可以使用 translateLabel() 方法自动翻译标签:

use Filament\Tables\Filters\Filter;

Filter::make('is_featured')->translateLabel() // Equivalent to `label(__('Is featured'))`

使用开关按钮(Toggle)代替复选框

默认情况下,过滤器使用复选框(Checkbox)控制过滤行为。你可以使用 toggle() 方法切换到开关按钮:

use Filament\Tables\Filters\Filter;

Filter::make('is_featured')->toggle()

默认过滤器

你可以使用 default() 方法,将过滤器设为默认启用:

use Filament\Tables\Filters\Filter;

Filter::make('is_featured')->label('Featured')->default()

过滤表单

默认情况下,过滤器有两种状态:可用和禁用。当过滤器启用时,会启用查询。如果禁用则相反。它通过复选框进行控制。不过有些过滤器可能要求额外的数据输入去进一步限制查询结果。你可以使用自定义过滤表单来收集这些数据。

下拉列表过滤器

下拉列表过滤器让你快速创建一个过滤器,允许用户通过下拉选项使用表格过滤器。比如,状态过滤器可能会提供一些状态选项让用户选择,过滤表格数据:

use Filament\Tables\Filters\SelectFilter;

SelectFilter::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])

下拉列表过滤器不需要自定义 query 方法。用于定义查询范围的字段名是过滤器的名称。要自定义查询字段名,你可以使用 column() 方法:

use Filament\Tables\Filters\SelectFilter;

SelectFilter::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
->column('status_id')

多选下拉列表过滤器

允许用户通过选择多个选项来使用表格过滤器。比如,状态过滤器可能会提供一些状态选项让用户选择,过滤表格数据:

use Filament\Tables\Filters\SelectFilter;

SelectFilter::make('status')
->multiple()
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])

关联下拉列表过滤器

选项框过滤器也能够基于 BelongsTo 关联自动填充数据。比如,你表格有使用了 name 字段的 author 关联,你可以使用 relationship() 过滤属于该作者的记录:

use Filament\Tables\Filters\SelectFilter;

SelectFilter::make('author')->relationship('author', 'name')

使用 relationship() 方法的第三个参数,你可以自定义检索选项的数据库查询:

use Filament\Tables\Filters\SelectFilter;
use Illuminate\Database\Eloquent\Builder;

SelectFilter::make('author')
->relationship('author', 'name', fn (Builder $query) => $query->withTrashed())

三元过滤器

三元过滤器(Ternary Filter)让你可以快速创建有三个状态的过滤器 - 通常为 true、false 和 blank。要过滤 is_admin 字段为 truefalse,你可以使用三元过滤器:

use Filament\Tables\Filters\TernaryFilter;

TernaryFilter::make('is_admin')

另一种通用的模式是可空值的字段。比如,使用 email_verified_at 字段来过滤验证和未验证用户时,未验证用户该字段值通常为空。你可以使用 nullable() 方法来适用这一逻辑:

use Filament\Tables\Filters\TernaryFilter;

TernaryFilter::make('email_verified_at')
->nullable()

用来限定查询范围的字段名就是过滤器的名称。要自定义查询字段,你可以使用 column() 方法:

use Filament\Tables\Filters\TernaryFilter;

TernaryFilter::make('verified')
->nullable()
->column('status_id')

你也可以使用 queries() 方法为三元过滤器的每一个状态自定义查询:

use Illuminate\Database\Eloquent\Builder;
use Filament\Tables\Filters\TernaryFilter;

TernaryFilter::make('trashed')
->placeholder('Without trashed records')
->trueLabel('With trashed records')
->falseLabel('Only trashed records')
->queries(
true: fn (Builder $query) => $query->withTrashed(),
false: fn (Builder $query) => $query->onlyTrashed(),
blank: fn (Builder $query) => $query->withoutTrashed(),
)

自定义过滤器表

你可以使用表单构造器的组件来创建自定义过滤器表单。自定义过滤器表单里的数据可以在 query() 回调函数中的 $data 数组中获取:

use Filament\Forms;
use Filament\Tables\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;

Filter::make('created_at')
->form([
Forms\Components\DatePicker::make('created_from'),
Forms\Components\DatePicker::make('created_until'),
])
->query(function (Builder $query, array $data): Builder {
return $query
->when(
$data['created_from'],
fn (Builder $query, $date): Builder => $query->whereDate('created_at', '>=', $date),
)
->when(
$data['created_until'],
fn (Builder $query, $date): Builder => $query->whereDate('created_at', '<=', $date),
);
})

设置默认值

如果你想要设置过滤器的默认值,可在表单组件中使用 default() 方法:

use Filament\Forms;
use Filament\Tables\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;

Filter::make('created_at')
->form([
Forms\Components\DatePicker::make('created_from'),
Forms\Components\DatePicker::make('created_until')->default(now()),
])

激活指示器

当过滤器激活时,会在表格内容的上面显示一个指示器,指示表格查询已经进行了筛选。

默认情况下,过滤器的标签被用作指示器。你可以对其进行重写:

use Filament\Tables\Filters\TernaryFilter;

TernaryFilter::make('is_admin')
->label('Administrators only?')
->indicator('Administrators')

自定义指示器

有些指示器比较复杂,你可以使用 indicateUsing() 自定义展示哪一个指示器。

比如,你有一个自定义的日期过滤器,你可以创建一个自定义的指示器来格式化选中的日期:

use Filament\Forms\Components\DatePicker;
use Filament\Tables\Filters\Filter;

Filter::make('created_at')
->form([DatePicker::make('date')])
// ...
->indicateUsing(function (array $data): ?string {
if (! $data['date']) {
return null;
}

return 'Created at ' . Carbon::parse($data['date'])->toFormattedDateString();
})

通过返回数组,你甚至可以一次渲染多个指示器。如果你有多个字段关联多个指示器,应该使用字段名作为数组的键,确保过滤器删除时能正确重置对应字段:

use Filament\Forms\Components\DatePicker;
use Filament\Tables\Filters\Filter;

Filter::make('created_at')
->form([
DatePicker::make('from'),
DatePicker::make('until'),
])
// ...
->indicateUsing(function (array $data): array {
$indicators = [];

if ($data['from'] ?? null) {
$indicators['from'] = 'Created from ' . Carbon::parse($data['from'])->toFormattedDateString();
}

if ($data['until'] ?? null) {
$indicators['until'] = 'Created until ' . Carbon::parse($data['until'])->toFormattedDateString();
}

return $indicators;
})

外观

默认情况下,过滤器以 1 列宽小弹窗显示在表格的右边。

要调整过滤器可能占据的列宽,你可以使用 getTableFiltersFormColumns() 方法:

protected function getTableFiltersFormColumns(): int
{
return 3;
}

添加列数到过滤器会自动增加弹窗宽度。要自定义弹窗宽度,你可以使用 getTableFiltersFormWidth() 方法,指定 xs7xl 之间的宽度值:

protected function getTableFiltersFormWidth(): string
{
return '4xl';
}

在表格内容上面显示过滤器

如果想在表格内容的顶部启用过滤器,代替弹窗方式,你可以使用:

use Filament\Tables\Filters\Layout;

protected function getTableFiltersLayout(): ?string
{
return Layout::AboveContent;
}

如果想在表格内容的底部启用过滤器,代替弹窗方式,你可以使用:

use Filament\Tables\Filters\Layout;

protected function getTableFiltersLayout(): ?string
{
return Layout::BelowContent;
}

在 Session 中持久化过滤器

要在用户 Session 中持久化表格过滤器,请使用 shouldPersistTableFiltersInSession() 方法:

protected function shouldPersistTableFiltersInSession(): bool
{
return true;
}