自定义数据
简介
Filament 的表格构造器最初是设计成使用 Laravel 中的 Eloquent 模型直接从数据库获取渲染数据的。Filament 表格中的每一行对应数据库的每一条记录,即一个 Eloquent 实例。
然而,这种设置并不总是可行或符合实际的。你可能需要显示未存储在数据库中的数据,或者存储但无法通过 Eloquent 访问的数据。
这种情况下,你可以使用自定义数据。请将一个返回数据数组的函数传递给表格构造器的 records()
方法。该函数在表格渲染时调用,它返回的值将用于填充表格。
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->records(fn (): array => [
1 => [
'title' => 'First item',
'slug' => 'first-item',
'is_featured' => true,
],
2 => [
'title' => 'Second item',
'slug' => 'second-item',
'is_featured' => false,
],
3 => [
'title' => 'Third item',
'slug' => 'third-item',
'is_featured' => true,
],
])
->columns([
TextColumn::make('title'),
TextColumn::make('slug'),
IconColumn::make('is_featured')
->boolean(),
]);
}
NOTE
数组键 (e.g., 1, 2, 3)
表示的是记录的 ID。请使用唯一的,有一致性的值以确保正确区分及状态跟踪。这有助于防止在Livewire 交互和更新过程中出现记录完整性问题。
列字段
表格中的列字段与使用 Eloquent 模型时的工作方式相似,但有一个关键区别:列名表示records()
函数返回的数组中的一个键,而不是引用模型属性或关联。
当在列函数中使用当前记录时,请将 $record
类型设 置为 array
而非 Model
。比如,要使用 state()
函数定义列时,你应该这样:
use Filament\Tables\Columns\TextColumn;
TextColumn::make('is_featured')
->state(function (array $record): string {
return $record['is_featured'] ? 'Featured' : 'Not featured';
})
排序
Filament 的内置排序函数使用 SQL 进行排序。当使用自定义数据时,你需要自己处理排序。
要获取当前的排序列字段和排序方向,你可以将 $sortColumn
和 $sortDirection
注入到 records()
函数。如果没有使用排序,这些变量为 null
。
下例中,有一个集合用于根据键排序数据。其返回的是集合而非数组,而 Filament 处理的方式与数组相同。不过使用集合不一定非得使用该特性。
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Support\Collection;
public function table(Table $table): Table
{
return $table
->records(
fn (?string $sortColumn, ?string $sortDirection): Collection => collect([
1 => ['title' => 'First item'],
2 => ['title' => 'Second item'],
3 => ['title' => 'Third item'],
])->when(
filled($sortColumn),
fn (Collection $data): Collection => $data->sortBy(
$sortColumn,
SORT_REGULAR,
$sortDirection === 'desc',
),
)
)
->columns([
TextColumn::make('title')
->sortable(),
]);
}
NOTE
看起来像是应该由 Filament 来帮你排序,不过很多情况下,最好是由你的数据源(比如自定义查询或者 API 调用)来处理排序。
搜索
Filament 的内置搜索函数使用 SQL 来搜索数据。当使用自定义数据时,你需要自己处理搜索。
要访问当前搜索查询,你可以将 $search
注入 records()
函数。如果当前未使用搜索查询,则此变量为 null
。
在下例中,使用集合根据搜索查询过滤数据。返回的是集 合而不是数组,Filament 的处理方式相同。但是,使用此功能并非必须使用集合。
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
public function table(Table $table): Table
{
return $table
->records(
fn (?string $search): Collection => collect([
1 => ['title' => 'First item'],
2 => ['title' => 'Second item'],
3 => ['title' => 'Third item'],
])->when(
filled($search),
fn (Collection $data): Collection => $data->filter(
fn (array $record): bool => str_contains(
Str::lower($record['title']),
Str::lower($search),
),
),
)
)
->columns([
TextColumn::make('title'),
])
->searchable();
}
此例中,像 title
这样的特定列不需要 searchable()
,因为搜索逻辑已在 records()
函数中处理。但是,如果你想启用搜索字段而不启用特定列的搜索功能,则可以对整个表使用 searchable()
方法。
NOTE
看起来像是应该由 Filament 来帮你搜索数据,不过很多情况下,最好是由你的数据源(比如自定义查询或者 API 调用)来处理搜索。