🚀

爆速CRUD管理画面作成パッケージ:Filamentの使い方

2023/01/27に公開
4

Filamentの使い方

Filament is 何?

FilamentはLaravel, Livewire, Alpine.js, Tailwindcssを使ったTALLスタックと呼ばれる構成で作られたLaravel用CRUD機能作成パッケージです

Filamentを使うことでLaravelのモデルデータをお手軽に編集可能な画面をサクサク作れてしまいます

各機能別ページ(初めての人は、この一通りの使い方ガイドを読んでね)

Filament:一通りの使い方ガイド

新規のLaravelプロジェクト作成

ここでは filabel というプロジェクト名でやっていきます

% laravel new filavel
% cd filavel
% touch database/database.sqlite
% vi .env

.envの編集

---before---
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=filavel
DB_USERNAME=root
DB_PASSWORD=
----------------after---
DB_CONNECTION=sqlite
-----------

Filamentのインストール

composer require filament/filament:"^2.0"

サンプルモデル作成

php artisan make:model -m Post
php artisan make:model -m Tag

モデルのマイグレーション作成

database/migrations/yyyy_mm_dd_hhmmss_create_posts_table.php
--------
public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->timestamps();
    });
}
----------------
public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');	//追加
        $table->text('body');	//追加
        $table->timestamps();
    });
}
--------
database/migrations/yyyy_mm_dd_hhmmss_create_tags_table.php
--------
public function up()
{
    Schema::create('tags', function (Blueprint $table) {
        $table->id();
        $table->timestamps();
    });
}
----------------
public function up()
{
    Schema::create('tags', function (Blueprint $table) {
        $table->id();
        $table->string('name')->unique();	//追加
        $table->timestamps();
    });
}
--------

モデルリレーションシップテーブル作成

php artisan make:migration create_post_tag_table

リレーションシップのマイグレーション作成

database/migrations/yyyy_mm_dd_hhmmss_create_post_tag_table.php
--------
public function up()
{
    Schema::create('post_tag', function (Blueprint $table) {
        $table->id();
        $table->timestamps();
    });
}
----------------
public function up()
{
    Schema::create('post_tag', function (Blueprint $table) {
        $table->id();
        $table->unsignedInteger('post_id');
        $table->unsignedInteger('tag_id');
        $table->foreign('post_id')->references('id')->on('posts')->cascadeOnDelete();
        $table->foreign('tag_id')->references('id')->on('tags')->cascadeOnDelete();
        $table->unique(['post_id','tag_id']);
        $table->timestamps();
    });
}
--------

マイグレーション実行

php artisan migrate

Postモデルの設定

app/Models/Post.php
------
class Post extends Model
{
    use HasFactory;
    protected $fillable = ['title', 'body'];  //追加
    
    //下記も追加
    public function tags() 
    {
        return $this->belongsToMany(Tag::class);
    }
}
------

Tagモデルの設定

app/Models/Tag.php
------
class Tag extends Model
{
    use HasFactory;
    protected $fillable = ['name'];  //追加
}
------

Filament用管理ユーザ作成

php artisan make:filament-user

 Name:
 > admin (管理者ユーザの名前入力)

 Email address:
 > admin@localhost (管理者ユーザのメアド入力)

 Password:
 >  (管理者ユーザのパスワード入力)

Success! admin@localhost may now log in at http://filavel.test/admin/login.

 Would you like to show some love by starring the repo? (yes/no) [yes]:
→ Filamentを気に入った時は yes と入力すると GitHub のリポに飛ぶので、スター押してね

Filamentにログイン

php artisan serve

ブラウザで http://localhost:8000/admin/login にアクセスする

ログイン認証画面が現れるので、管理ユーザ作成で入力したメールアドレスとパスワードでログインする
8AF46A54-3446-4781-9153-649518B5964F

Filament用管理リソースを作成する

Filamentの管理画面でモデルのデータが扱えるようにリソースを作成します。

ちなみに
基本を飛ばして自動生成機能で楽したい人はこちらをご確認ください

リソース作成の基本を見たい人は、このまま👇の手順を進めてください

php artisan make:filament-resource Post
php artisan make:filament-resource Tag

PostResource.phpファイルを編集します

app/Filament/Resources/PostResource.php
---before---
public static function form(Form $form): Form
{
    return $form
        ->schema([
            //
        ]);
}

public static function table(Table $table): Table
{
    return $table
        ->columns([
            //
        ])
        ->filters([
            //
        ])
        ->actions([
            Tables\Actions\EditAction::make(),
        ])
        ->bulkActions([
            Tables\Actions\DeleteBulkAction::make(),
        ]);
}
--------------after---
public static function form(Form $form): Form
{
    return $form
        ->schema([
            // ここに編集したい項目を追加する
            Forms\Components\TextInput::make('title')->required()->label('タイトル')
                ->hint("ブログのタイトル入力"),
            Forms\Components\Textarea::make('body')->required()->label('本文')
                ->helperText('本文を入力します')
                ->columnSpan('full'),
        ]);
}

public static function table(Table $table): Table
{
    return $table
        ->columns([
            // ここに表示したい項目を追加する
            Tables\Columns\TextColumn::make('title')->label('タイトル'),
            Tables\Columns\TextColumn::make('body')->label('本文'),
        ])
        ->filters([
            //
        ])
        ->actions([
            Tables\Actions\EditAction::make(),
        ])
        ->bulkActions([
            Tables\Actions\DeleteBulkAction::make(),
        ]);
}
-----------

TagResource.phpファイルを編集します

app/Filament/Resources/TagResource.php
---before---
public static function form(Form $form): Form
{
    return $form
        ->schema([
            //
        ]);
}

public static function table(Table $table): Table
{
    return $table
        ->columns([
            //
        ])
        ->filters([
            //
        ])
        ->actions([
            Tables\Actions\EditAction::make(),
        ])
        ->bulkActions([
            Tables\Actions\DeleteBulkAction::make(),
        ]);
}
--------------after---
public static function form(Form $form): Form
{
    return $form
        ->schema([
            // ここに編集したい項目を追加する
            Forms\Components\TextInput::make('name')->required()->label('タグ')
                ->hint("タグ名を入力"),
        ]);
}

public static function table(Table $table): Table
{
    return $table
        ->columns([
            // ここに表示したい項目を追加する
            Tables\Columns\TextColumn::make('name')->label('タグ'),
        ])
        ->filters([
            //
        ])
        ->actions([
            Tables\Actions\EditAction::make(),
        ])
        ->bulkActions([
            Tables\Actions\DeleteBulkAction::make(),
        ]);
}
-----------

管理画面の変更確認

管理画面にアクセスすると作成した各モデルリソースが表示されている(まだデータは無い)

149305F4-7BA3-4255-89AD-A46B215669D5

こちらはTagモデル(まだデータは無い)
A5428CCF-E8B2-4261-B7FE-3AE63BEAA388

Postsリソースの右側の”New Post”をクリックして新規データを作成してみよう

59CCB38C-1F02-412F-808A-E0826D998B47

タイトルと本文を入力して”Create”をクリック
9CFE0CF3-5736-45EF-9168-8BCBE4BA4EB5

右上に”Created”と表示されたら作成成功(保存時に一覧画面に戻りたい場合はこちら)。左側のメニューのPostsをクリックして作成されたデータを見てみよう
435AB861-0F33-4E78-AA68-13579A31524F

作成したデータが一覧に表示される(項目でソートしたい場合はこちら
800B4CDA-56A0-4190-9E08-DAE863783CA7

ちなみにここでモデル名の箇所をLaravelのモデル名じゃなく、日本語で適切な名前を表示したい場合にはこちらを参照

Filamentメニューの日本語化

そのままだとFilamentの各種メニューは英語表記なので、configを修正して日本語化しましょう

config/app.php
---before---
    'locale' => 'en',
---------------after---
    'locale' => 'ja',
-----------

再度管理画面にアクセスするとメニューが日本語に変わっています。ちなみに項目の検索機能をつけたい方は 👉こちら
6F7D2D95-F8BC-497E-A346-B53B76E303C2

作成ボタンをクリック後も各種ボタンやラベルが日本語表記になります
470FAB7A-C36C-4158-AE78-A603B63ED084

ちなみに自分の方でFilamentのリリースv2.15.29の#3716、#3717、#3718のPRとリリースv2.16.13の#4152、#4153、#4154のPR、リリースv2.16.17の#4202、#4203、リリースv2.16.19の#4294で日本語化に貢献してます😏

Filamentリレーションリソースの追加

php artisan make:filament-relation-manager PostResource tags name

PostモデルからTagの新規作成&割当を可能にするボタン追加

app/Filament/Resources/PostResource/RelationManagers/TagsRelationManager.php
---before---
public static function table(Table $table): Table
{
    return $table
        ->columns([
            Tables\Columns\TextColumn::make('name'),
        ])
        ->filters([
            //
        ])
        ->headerActions([
            Tables\Actions\CreateAction::make(),
        ])
        (省略)
}    
---------------after---
public static function table(Table $table): Table
{
    return $table
        ->columns([
            Tables\Columns\TextColumn::make('name'),
        ])
        ->filters([
            //
        ])
        ->headerActions([
            Tables\Actions\CreateAction::make(),
            Tables\Actions\AttachAction::make()->preloadRecordSelect()->label('タグ追加'), //追加
        ])
        (省略)
}    
-----------

PostResourceにTagとのリレーションシップを追加

app/Filament/Resources/PostResource.ph
---before---
public static function getRelations(): array
{
    return [
        //
    ];
}
---------------after---
public static function getRelations(): array
{
    return [
        PostResource\RelationManagers\TagsRelationManager::class, //追加
    ];
}
------------

管理画面にアクセスし動作確認

Tagの右側にある作成をクリック
9E7534FC-6B64-4FE4-B178-C6A852C9571C

作成ウィンドウが開くのでタグ名を入力し作成をクリック
11307C25-7A35-426F-8BA4-8475080720EB

Postデータに新規に作成されたTagデータが紐づきます
14A98190-BA8F-4288-BAA0-C6C2C9A45485

既存データの追加

他のタグが存在する場合「タグ追加」ボタンから、既存のタグを付与することもできます。
46084205-C9AE-400E-BBED-AEC4526898CE

Postデータから編集をクリックし、表示された編集画面のTagの右端にある「タグ追加」ボタンをクリック
D32E255A-CB34-4B5F-9766-FFE2A1FF3D4B

表示されるタグ追加ウィンドウから既存のデータがドロップダウンや検索機能による絞り込みで選べます
4D1AD9C1-A8BA-4661-B518-D6B5D14636DD

リレーションシップの付け替えについて

ちなみにこの画面の削除ボタンをクリックするとリレーションシップが外れるのではなく、sampleタグ自体が削除されてしまいます😱
4D1AD9C1-A8BA-4661-B518-D6B5D14636DE

これを防ぐには TagsRelationManager.php を以下のように変更します

app/Filament/Resources/PostResource/RelationManagers/TagsRelationManager.php
---before---
public static function table(Table $table): Table
{
    return $table
        ->columns([
            Tables\Columns\TextColumn::make('name'),
        ])
        ->filters([
            //
        ])
        ->headerActions([
            Tables\Actions\CreateAction::make(),
            Tables\Actions\AttachAction::make()->preloadRecordSelect()->label('タグ追加'),
        ])
        ->actions([
            Tables\Actions\EditAction::make(),
            Tables\Actions\DeleteAction::make(),
        ])
        ->bulkActions([
            Tables\Actions\DeleteBulkAction::make(),
        ]);
}
---------------after---
public static function table(Table $table): Table
{
    return $table
        ->columns([
            Tables\Columns\TextColumn::make('name'),
        ])
        ->filters([
            //
        ])
        ->headerActions([
            Tables\Actions\CreateAction::make(),
            Tables\Actions\AttachAction::make()->preloadRecordSelect()->label('タグ追加'),
        ])
        ->actions([
            Tables\Actions\EditAction::make(),
            Tables\Actions\DetachAction::make(),  //ここをDeleteからDetachにしたよ
        ])
        ->bulkActions([
            Tables\Actions\DeleteBulkAction::make(),
        ]);
}
-----------

これで一安心😄

4D1AD9C1-A8BA-4661-B518-D6B5D14636DD

Userモデルの管理画面

ユーザモデルは新規登録時のメールアドレスのユニーク制限やパスワードのハッシュ化等、色々と考えるべきことが多いので、こちらの別枠ドキュメントを参考願います

カスタムページの追加

Filamentではリソースコンポーネントだけではなく、個別のカスタムページを作成して追加することも出来ます。詳しくはこちらをご覧ください

追加情報

より詳しい情報はオフィシャルドキュメントを読もう👉
Installation - Admin Panel - Filament

元ネタはこちら

この記事が気に入ったらサポートしてね💕

ko-fi

GitHubで編集を提案

Discussion

kigokigo

こちらの記事で初めてFilamentを知りました。

使ってみたいと思って試しに作ってみたのですが、
モデルリソースの一覧からEditページを開いて、Deleteボタン → Confirmを押すと、一瞬エラーが表示されて、一覧の画面に戻ります。

ログ(laravel.log)を見ると下記のエラーが出ていました。

Missing required parameter for [Route: filament.resources.posts.edit] [URI: admin/posts/{record}/edit] [Missing parameter: record]. {">[stacktrace]

ComposerでLaravelプロジェクトを作成した場合、Laravel Sailでプロジェクトを作成した場合の両方とも同じ現象が起きます。
何か原因は分かりますでしょうか?

circlebackcircleback

試しにここの手順通りにPostモデルを作ってデータ作成と削除をやってみたのですけど、特にエラーは発生しないですね

admin/posts/{record}/edit[Missing parameter: record]と怒られてるので、恐らく該当のデータを削除後に再度同一データの編集画面を開こうとして(既にデータ削除済みなので)エラーになってる雰囲気です

理由は不明ですが

composer dump-autoload

php artisan filament:upgrade

とか試してみてください

kigokigo

返信ありがとうございます。
circlebackさんの場合はエラーは発生しないんですね。

composer dump-autoload
php artisan filament:upgrade

を試してみましたが、症状は変わらずでした。

今回エラーが発生していたのがWindows環境でしたので、試しにエックスサーバー上で作成してみたら、こちらはエラーが発生しませんでした。
Windows環境のせいなのか、私の環境(PHP等)がおかしいのか…
もう少し調べてみたいと思います。

circlebackcircleback

なるほど

自分の環境はMacなのでちょっとお役に立てずに申し訳ないです

WindowsだとWSL2とか使ってバックグラウンドでubuntuを動かしてやってみるとかで解消するかも?(既にお試し済みなら申し訳ない)