昨天提到了一部分的 Filament 客製化,今天繼續來聊其他的客製化選項
在前面的範例內,我們在設定關聯時,Filament 根據欄位的屬性預設給我們是使用文字來編輯 category_id
這類關聯資料 ID
這個做法對一般後台操作者來說,確實有些不直覺。所以 Filament 提供可以用下拉選單的做法。
app/Filament/Resources/Products/Schemas/ProductForm.php
的
TextInput::make('category_id')
->numeric(),
改成
Select::make('category_id')
->label('Category')
->options(Category::query()->pluck('name', 'id'))
->searchable(),
就可以使用下拉選單編輯了
如果要在列表頁也可以編輯,那麼就要改用 SelectColumn
app/Filament/Resources/Products/Tables/ProductsTable.php
的
TextColumn::make('category_id')
->numeric()
->sortable(),
改成
SelectColumn::make('category_id')
->label('Category')
->options(Category::query()->pluck('name', 'id'))
->searchable(),
就可以在列表頁面進行編輯了
並且是修改後立刻生效
如果是商品跟分類頁面,前面的部分可能問題不大
不過如果是我們當初做的商品圖片
class ProductImage extends Model
{
/** @use HasFactory<\Database\Factories\ProductImageFactory> */
use HasFactory;
protected $fillable = [
'product_id', 'url', 'alt', 'is_primary', 'sort_order', 'is_active',
];
public function casts(): array
{
return [
'is_primary' => 'boolean',
'is_active' => 'boolean',
];
}
public function product(): BelongsTo
{
return $this->belongsTo(Product::class);
}
}
可能會有後台操作者抱怨,編輯時忘記檢查一個商品內的圖片是不是只有一個 primary,或者 sort order 重複。
雖然很想跟客戶說這難道不是可以用員工教育解決掉的事情嗎,但是想想還是算了。
幸好,Filament 提供了 beforeStateUpdated()
可以讓我們在更新資料時進行檢查,甚至修改其他資料
首先我們先建立對應的 Filament Resource
php artisan make:filament-resource ProductImage
並微調一下,將 app/Filament/Resources/ProductImages/Tables/ProductImagesTable.php
裡面 is_primary
的 IconColumn
改成 ToggleColumn
class ProductImagesTable
{
public static function configure(Table $table): Table
{
return $table
->columns([
SelectColumn::make('product_id')
->label('product')
->options(Product::query()->pluck('name', 'id'))
->searchable(),
TextColumn::make('product_id')
->numeric()
->sortable(),
TextColumn::make('url')
->searchable(),
TextColumn::make('alt')
->searchable(),
ToggleColumn::make('is_primary'),
TextColumn::make('sort_order')
->numeric()
->sortable(),
IconColumn::make('is_active')
->boolean(),
TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->recordActions([
ViewAction::make(),
EditAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
}
}
這時候我們是可以將同一商品的多張圖片都設置為 primary 的
不過,當我們加上 beforeStateUpdated()
,在裡面設定調整前將同商品的其他商品圖片 is_primary
都設置為 false
之後
ToggleColumn::make('is_primary')
->beforeStateUpdated(function (ProductImage $record) {
ProductImage::whereProductId($record->product_id)
->whereKeyNot($record->id)
->update(['is_primary' => false]);
}),
在列表頁編輯時,Filament 就會去找出該商品下的所有圖片,並將他們的 is_primary
都設置為 false
了
今天的客製化部分就說到這邊,我們明天見!