#02 FilamentPHP基礎
はじめてのリソース——テーブルとフォームを作る
リソースとは何か
Filamentにおけるリソース(Resource)は、Laravelのモデルに対応するCRUD操作をまとめたクラスです。1つのリソースが「一覧・作成・編集・削除」という4つの操作を担います。
PostResource
├── 一覧ページ (ListPosts) → GET /admin/posts
├── 作成ページ (CreatePost) → GET /admin/posts/create
├── 編集ページ (EditPost) → GET /admin/posts/{record}/edit
└── 削除ボタン → DELETE /admin/posts/{record}
Railsの scaffold やLaravel Novaの Resource と似た概念ですが、Filamentのリソースは PHPコードだけで完結 するのが特徴です。Bladeテンプレートを書く必要はありません。
Postモデルを準備する
まずリソースの土台となるモデルとマイグレーションを作成します。
php artisan make:model Post -m
マイグレーションファイルを編集します。
<?php
// 📁 database/migrations/xxxx_create_posts_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content')->nullable();
$table->boolean('is_published')->default(false);
$table->timestamp('published_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('posts');
}
};
php artisan migrate
Postモデルに fillable を設定します。
<?php
// 📁 app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = [
'title',
'content',
'is_published',
'published_at',
];
protected $casts = [
'is_published' => 'boolean',
'published_at' => 'datetime',
];
}
リソースを生成する
php artisan make:filament-resource Post --generate
--generate オプションを付けると、モデルのカラムをもとにフォームとテーブルを自動生成してくれます。
生成されるファイル:
app/Filament/Resources/
└── PostResource/
├── PostResource.php ← メインファイル
└── Pages/
├── ListPosts.php ← 一覧ページ
├── CreatePost.php ← 作成ページ
└── EditPost.php ← 編集ページ
PostResource.php の構造
生成された PostResource.php を確認しましょう。
<?php
// 📁 app/Filament/Resources/PostResource.php
namespace App\Filament\Resources;
use App\Filament\Resources\PostResource\Pages;
use App\Models\Post;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
class PostResource extends Resource
{
// 対応するEloquentモデル
protected static ?string $model = Post::class;
// サイドバーに表示するアイコン(Heroicons)
protected static ?string $navigationIcon = 'heroicon-o-document-text';
// フォームの定義
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('title')
->required()
->maxLength(255),
Forms\Components\Textarea::make('content')
->columnSpanFull(),
Forms\Components\Toggle::make('is_published'),
Forms\Components\DateTimePicker::make('published_at'),
]);
}
// テーブル(一覧)の定義
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('title')
->searchable(),
Tables\Columns\IconColumn::make('is_published')
->boolean(),
Tables\Columns\TextColumn::make('published_at')
->dateTime()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
// 関連するページクラスを登録
public static function getPages(): array
{
return [
'index' => Pages\ListPosts::route('/'),
'create' => Pages\CreatePost::route('/create'),
'edit' => Pages\EditPost::route('/{record}/edit'),
];
}
}
3つのメソッドの役割
| メソッド | 役割 |
|---|---|
form() | 作成・編集画面のフォームを定義 |
table() | 一覧画面のテーブルを定義 |
getPages() | ルートとページクラスの対応を定義 |
フォームフィールドを整える
自動生成されたフォームを実用的に改良します。
public static function form(Form $form): Form
{
return $form
->schema([
// タイトル入力欄
Forms\Components\TextInput::make('title')
->label('タイトル')
->required()
->maxLength(255)
->placeholder('記事タイトルを入力してください'),
// 本文テキストエリア
Forms\Components\Textarea::make('content')
->label('本文')
->rows(8)
->columnSpanFull(), // 2カラムレイアウトでも全幅表示
// 公開フラグ(トグルスイッチ)
Forms\Components\Toggle::make('is_published')
->label('公開する')
->default(false),
// 公開日時
Forms\Components\DateTimePicker::make('published_at')
->label('公開日時')
->nullable(),
]);
}
主要なフォームフィールド
// テキスト入力
Forms\Components\TextInput::make('name')
->label('名前')
->required();
// 複数行テキスト
Forms\Components\Textarea::make('description')
->rows(4);
// トグル(真偽値)
Forms\Components\Toggle::make('is_active');
// セレクトボックス
Forms\Components\Select::make('status')
->options([
'draft' => '下書き',
'published' => '公開',
'archived' => 'アーカイブ',
]);
// 日時ピッカー
Forms\Components\DateTimePicker::make('published_at');
テーブルカラムを整える
public static function table(Table $table): Table
{
return $table
->columns([
// テキストカラム(検索・ソート対応)
Tables\Columns\TextColumn::make('title')
->label('タイトル')
->searchable()
->sortable()
->limit(50), // 50文字で切り捨て
// 真偽値カラム(アイコン表示)
Tables\Columns\IconColumn::make('is_published')
->label('公開')
->boolean(), // true=チェック, false=バツ
// 日時カラム
Tables\Columns\TextColumn::make('published_at')
->label('公開日時')
->dateTime('Y/m/d H:i')
->sortable(),
// 作成日(デフォルトで非表示)
Tables\Columns\TextColumn::make('created_at')
->label('作成日')
->dateTime('Y/m/d')
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->defaultSort('created_at', 'desc') // デフォルトのソート順
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
ページクラスの役割
ListPosts.php(一覧ページ)
<?php
// 📁 app/Filament/Resources/PostResource/Pages/ListPosts.php
namespace App\Filament\Resources\PostResource\Pages;
use App\Filament\Resources\PostResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListPosts extends ListRecords
{
protected static string $resource = PostResource::class;
// 右上に「新規作成」ボタンを追加
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}
CreatePost.php(作成ページ)
<?php
// 📁 app/Filament/Resources/PostResource/Pages/CreatePost.php
namespace App\Filament\Resources\PostResource\Pages;
use App\Filament\Resources\PostResource;
use Filament\Resources\Pages\CreateRecord;
class CreatePost extends CreateRecord
{
protected static string $resource = PostResource::class;
// 作成後のリダイレクト先をカスタマイズ
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
}
EditPost.php(編集ページ)
<?php
// 📁 app/Filament/Resources/PostResource/Pages/EditPost.php
namespace App\Filament\Resources\PostResource\Pages;
use App\Filament\Resources\PostResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditPost extends EditRecord
{
protected static string $resource = PostResource::class;
// 右上に「削除」ボタンを追加
protected function getHeaderActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
動作確認
開発サーバーを起動して /admin/posts にアクセスします。
php artisan serve
http://localhost:8000/admin/posts→ 一覧画面http://localhost:8000/admin/posts/create→ 作成画面
「新規投稿」ボタンをクリックしてタイトルと本文を入力し、「作成」ボタンを押してみましょう。一覧に追加されていれば成功です。
まとめ
- Filamentのリソースはモデルに対応するCRUDのまとまり
php artisan make:filament-resource Post --generateで自動生成form()でフォームを、table()でテーブルを定義getPages()でURL→ページクラスの対応を管理- 3つのページクラス(List/Create/Edit)がそれぞれの画面を担う
次回はフォームフィールドを深掘りし、Select・DatePicker・FileUploadなどの使い方を学びます。