博客

怎样使用 Filament Table 消费外部 API

Dec 11, 2022
Roger
Admin panel, Table builder

介绍

有时,我们使用 Filament Table 时数据源并非来自于数据库表。

本例将允许你从外部数据源获取数据(JSON API)提供给模型。

配置

安装 calebporzio/sushi 包:

composer require calebporzio/sushi

新建 Product 模型和 Product Resource:

php artisan make:model Product
php artisan make:filament-resource Product --simple --view

将 Sushi trait 添加到 Product 模型。你可以执行 getRows() 方法从外部源获取数据。

//app\Models\Product.php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Sushi\Sushi;
 
class Product extends Model
{
use Sushi;
 
/**
* Model Rows
*
* @return void
*/
public function getRows()
{
//API
$products = Http::get('https://dummyjson.com/products')->json();
 
//filtering some attributes
$products = Arr::map($products['products'], function ($item) {
return Arr::only($item,
[
'id',
'title',
'description',
'price',
'rating',
'brand',
'category',
'thumbnail',
]
);
});
 
return $products;
}
}

你可以在 Product Resource 文件中创建表单字段和表格字段:

表单字段:

//app\Filament\Resources\ProductResource.php
 
use Filament\Forms\Components\RichEditor;
use Filament\Forms\Components\TextInput;
 
public static function form(Form $form): Form
{
return $form
->schema([
 
//title
TextInput::make('title'),
 
//brand
TextInput::make('brand'),
 
//category
TextInput::make('category'),
 
//description
RichEditor::make('description'),
 
//price
TextInput::make('price')
->prefix('$'),
 
//rating
TextInput::make('rating')
->numeric(),
]);
}

表格字段:

//app\Filament\Resources\ProductResource.php
 
use Filament\Tables\Columns\BadgeColumn;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
 
...
->columns([
 
//thumbnail
ImageColumn::make('thumbnail')
->label('Image')
->rounded(),
 
//title
TextColumn::make('title')
->searchable()
->sortable()
->weight('medium')
->alignLeft(),
 
//brand
TextColumn::make('brand')
->searchable()
->sortable()
->color('secondary')
->alignLeft(),
 
//category
TextColumn::make('category')
->sortable()
->searchable(),
 
//description
TextColumn::make('description')
->sortable()
->searchable()
->limit(30),
 
//price
BadgeColumn::make('price')
->colors(['secondary'])
->prefix('$')
->sortable()
->searchable(),
 
//rating
BadgeColumn::make('rating')
->colors([
'danger' => static fn ($state): bool => $state <= 3,
'warning' => static fn ($state): bool => $state > 3 && $state <= 4.5,
'success' => static fn ($state): bool => $state > 4.5,
])
->sortable()
->searchable(),
 
])

表格过滤器:

//app\Filament\Resources\ProductResource.php
 
use Filament\Tables\Filters\SelectFilter;
 
...
->filters([
 
//brand
SelectFilter::make('brand')
->multiple()
->options(Product::select('brand')
->distinct()
->get()
->pluck('brand', 'brand')
),
 
//category
SelectFilter::make('category')
->multiple()
->options(Product::select('category')
->distinct()
->get()
->pluck('category', 'category')
),
])

如你所见,API 是只读的。你可以隐藏一些Action按钮:

//app\Filament\Resources\ProductResource.php
 
...
->actions([
Tables\Actions\ViewAction::make(),
//Tables\Actions\EditAction::make(),
//Tables\Actions\DeleteAction::make(),
])
->bulkActions([
//Tables\Actions\DeleteBulkAction::make(),
])
//app\Filament\Resources\ProductResource\Pages\ManageProducts.php
protected function getActions(): array
{
return [
//Actions\CreateAction::make(),
];
}

现在可以到 /admin/products 中访问 Product 资源了!