#04 FilamentPHP基礎
テーブルカラムとフィルター——一覧画面を強化する
テーブルの構成要素
Filamentのテーブルは table() メソッドの中で以下の要素を定義します。
Table
├── columns() → 表示カラム
├── filters() → フィルター(絞り込み)
├── actions() → 行アクション(編集・削除ボタン等)
└── bulkActions() → 一括アクション(一括削除等)
すべて Tables\Columns・Tables\Filters・Tables\Actions 名前空間以下にあります。
TextColumn
最も基本的なカラムです。
use Filament\Tables\Columns\TextColumn;
// 基本
TextColumn::make('title')
->label('タイトル'),
// 検索・ソート対応
TextColumn::make('title')
->label('タイトル')
->searchable() // テーブル上部に検索ボックスが表示される
->sortable(), // ヘッダークリックでソート
// 文字数制限
TextColumn::make('content')
->label('本文')
->limit(80) // 80文字で切り捨て
->tooltip(fn ($record) => $record->content), // ホバーで全文表示
// 折り返し表示
TextColumn::make('description')
->wrap(), // テキストを折り返す
// フォーマット
TextColumn::make('price')
->money('JPY'), // ¥1,000 形式
TextColumn::make('published_at')
->dateTime('Y/m/d H:i') // 日時フォーマット
->since(), // "3時間前" のような相対表示
// 複数カラムを合わせて検索
TextColumn::make('name')
->searchable(query: function ($query, string $search) {
$query->where('first_name', 'like', "%{$search}%")
->orWhere('last_name', 'like', "%{$search}%");
}),
BadgeColumn(TextColumnのバッジ表示)
v5ではTextColumnに ->badge() を追加することでバッジ表示ができます。
TextColumn::make('status')
->label('ステータス')
->badge()
->color(fn (string $state): string => match ($state) {
'draft' => 'gray',
'review' => 'warning',
'published' => 'success',
'archived' => 'danger',
})
->formatStateUsing(fn (string $state): string => match ($state) {
'draft' => '下書き',
'review' => 'レビュー中',
'published' => '公開',
'archived' => 'アーカイブ',
default => $state,
}),
バッジに使えるカラー:primary / secondary / success / warning / danger / info / gray
ImageColumn
use Filament\Tables\Columns\ImageColumn;
ImageColumn::make('thumbnail')
->label('サムネイル')
->disk('public')
->size(60) // 幅・高さ60px(正方形)
->square(), // 正方形クリップ
// アバター(円形)
ImageColumn::make('avatar')
->circular(),
// サイズ個別指定
ImageColumn::make('thumbnail')
->width(120)
->height(80),
IconColumn
真偽値や状態をアイコンで表示します。
use Filament\Tables\Columns\IconColumn;
// 真偽値(チェック/バツ)
IconColumn::make('is_published')
->label('公開')
->boolean(),
// カスタムアイコンと色
IconColumn::make('status')
->icon(fn (string $state): string => match ($state) {
'draft' => 'heroicon-o-pencil',
'published' => 'heroicon-o-check-circle',
'archived' => 'heroicon-o-archive-box',
})
->color(fn (string $state): string => match ($state) {
'draft' => 'gray',
'published' => 'success',
'archived' => 'warning',
}),
ToggleColumn
一覧画面上で直接真偽値を切り替えられるカラムです。
use Filament\Tables\Columns\ToggleColumn;
ToggleColumn::make('is_active')
->label('有効'),
これだけでテーブル上にトグルスイッチが表示され、クリックするとその場でDBが更新されます。
searchable と sortable の詳細
// 関連テーブルのカラムも検索可能
TextColumn::make('author.name')
->label('著者')
->searchable(isIndividual: true), // 個別の検索ボックスを表示
// カスタムソート
TextColumn::make('full_name')
->sortable(query: function ($query, string $direction) {
$query->orderBy('last_name', $direction)
->orderBy('first_name', $direction);
}),
フィルター
->filters() でテーブルの絞り込み機能を追加します。
SelectFilter
use Filament\Tables\Filters\SelectFilter;
SelectFilter::make('status')
->label('ステータス')
->options([
'draft' => '下書き',
'published' => '公開',
'archived' => 'アーカイブ',
]),
// リレーションから選択肢を生成
SelectFilter::make('category_id')
->label('カテゴリ')
->relationship('category', 'name')
->searchable()
->preload(),
// 複数選択フィルター
SelectFilter::make('tags')
->relationship('tags', 'name')
->multiple()
->preload(),
TernaryFilter
3択(すべて/はい/いいえ)のフィルターです。
use Filament\Tables\Filters\TernaryFilter;
TernaryFilter::make('is_published')
->label('公開状態')
->trueLabel('公開のみ')
->falseLabel('未公開のみ')
->nullable(), // null値も扱う場合
// カスタムクエリ
TernaryFilter::make('has_thumbnail')
->label('サムネイル')
->trueLabel('あり')
->falseLabel('なし')
->queries(
true: fn ($query) => $query->whereNotNull('thumbnail'),
false: fn ($query) => $query->whereNull('thumbnail'),
),
TrashedFilter(ソフトデリート対応)
use Filament\Tables\Filters\TrashedFilter;
// Postモデルに SoftDeletes を使っている場合
TrashedFilter::make(),
モデル側の準備:
// 📁 app/Models/Post.php
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use SoftDeletes;
// ...
}
マイグレーションに softDeletes() も追加します。
$table->softDeletes(); // deleted_at カラムを追加
フィルターをまとめて定義する
public static function table(Table $table): Table
{
return $table
->columns([...])
->filters([
SelectFilter::make('status')
->options([
'draft' => '下書き',
'published' => '公開',
]),
SelectFilter::make('category_id')
->relationship('category', 'name')
->label('カテゴリ'),
TernaryFilter::make('is_published')
->label('公開'),
TrashedFilter::make(),
])
->filtersLayout(FiltersLayout::AboveContent); // フィルターを表の上に表示
}
デフォルトソートとページネーション
->defaultSort('created_at', 'desc') // デフォルトは作成日降順
->paginated([10, 25, 50, 100]) // ページあたりの件数の選択肢
->defaultPaginationPageOption(25) // デフォルトは25件
// ページネーション無効(全件表示)
->paginated(false)
一括アクション(BulkAction)
チェックボックスで複数行を選択して一括操作するボタンです。
->bulkActions([
Tables\Actions\BulkActionGroup::make([
// 一括削除(標準)
Tables\Actions\DeleteBulkAction::make(),
// ソフトデリートの復元
Tables\Actions\RestoreBulkAction::make(),
Tables\Actions\ForceDeleteBulkAction::make(),
// カスタム一括アクション
Tables\Actions\BulkAction::make('publish')
->label('一括公開')
->icon('heroicon-o-check')
->color('success')
->action(function (Collection $records) {
$records->each(function ($record) {
$record->update(['is_published' => true]);
});
})
->requiresConfirmation() // 確認ダイアログを表示
->deselectRecordsAfterCompletion(),
]),
])
行アクション(Action)
各行の右端に表示されるボタンです。
->actions([
Tables\Actions\ViewAction::make(), // 詳細表示
Tables\Actions\EditAction::make(), // 編集
Tables\Actions\DeleteAction::make(), // 削除
// カスタムアクション
Tables\Actions\Action::make('publish')
->label('公開')
->icon('heroicon-o-check-circle')
->color('success')
->visible(fn ($record) => ! $record->is_published)
->action(function ($record) {
$record->update([
'is_published' => true,
'published_at' => now(),
]);
})
->requiresConfirmation()
->modalHeading('記事を公開しますか?')
->modalDescription('公開すると一般ユーザーに表示されます。')
->modalSubmitActionLabel('公開する'),
])
まとめ
TextColumnは->searchable()/->sortable()/->limit()/->money()などで表示を制御->badge()でバッジ表示、->color()で条件付きカラーImageColumnは->circular()でアバター表示ToggleColumnで一覧上から直接値を編集できるSelectFilter/TernaryFilter/TrashedFilterで絞り込み->defaultSort()/->paginated()でテーブルの動作を設定BulkActionで複数行への一括操作ボタンを追加
次回はリレーションを持つリソースの扱い方を学びます。