LaravelとFilamentを使って管理画面を爆速構築
IT技術
こんにちは!
Laravelを使ったアプリを作る際に管理画面が必要になったのですが、Filamentというライブラリを使うと爆速でいい感じの管理画面を作ることができました!
今回はFilamentについて、簡単なブログ投稿機能を作りながら紹介していきたいと思います!
環境
- Mac M1
- Laravel 11
※事前に下記を対応している状態です。
Filamentの導入
既存のLaravelプロジェクト直下で次のコマンドを使ってFilamentを導入していきます。
1$ sail composer require filament/filament:"^3.2" -W
2$ sail php artisan filament:install --panels
次のように聞かれるので、2回ともデフォルトのままEnterキーを押します。
1 ┌ What is the ID? ─────────────────────────────────────────────┐
2 │ admin │
3 └──────────────────────────────────────────────────────────────┘
4
5┌ All done! Would you like to show some love by starring the Filament repo on GitHub? ┐
6│ ● Yes / ○ No │
7└─────────────────────────────────────────────────────────────────────────────────────┘
完了後に localhost/adminにアクセスすると、すでにログイン画面が完成しておりました。
ログインユーザーの作成
ではログインするためのユーザーを作成するために次のコマンドを実行します。
1$sail php artisan make:filament-user
すると下記のように「Name」と「Email address」と「Password」の入力を求められるので、設定してください。
1$ sail php artisan make:filament-user
2
3
4
5 ┌ Name ────────────────────────────────────────────────────────┐
6 │ test │
7 └──────────────────────────────────────────────────────────────┘
8
9 ┌ Email address ───────────────────────────────────────────────┐
10 │ test@demo.com │
11 └──────────────────────────────────────────────────────────────┘
12
13 ┌ Password ────────────────────────────────────────────────────┐
14 │ •••••••• │
15 └──────────────────────────────────────────────────────────────┘
16
17 INFO Success! test@demo.com may now log in at http://localhost/admin/login.
では、上記で設定したメールアドレスとパスワードを使って、ログインしてみましょう!
ログインに成功すると、下の画像のような画面になるかと思います!
モデルの追加とデータベースのセットアップ
先述した通り、簡単なブログ投稿機能を作っていくので、「投稿」と「カテゴリー」のモデルを次のコマンドを実行して追加します。
1$sail php artisan make:model Post -m
2$sail php artisan make:model Category -m
app/ModelsディレクトリにPost.phpファイルとCategory.phpファイル、databases/migrationsディレクトリにそれぞれのマイグレーションファイルが作成されます。
続いて、次のようにマイグレーションファイルを編集してテーブルの列を追加します。
1// YYYY_MM_DD_XXXXX_create_posts_table.php
2.
3.
4 public function up(): void
5 {
6 Schema::create('posts', function (Blueprint $table) {
7 $table->id();
8 $table->string('title'); // 追加部分
9 $table->text('content'); // 追加部分
10 $table->foreignId('user_id')->constrained('users')->cascadeOnDelete(); // 追加部分
11 $table->foreignId('category_id')->constrained('categories'); // 追加部分
12 $table->timestamps();
13 });
14 }
15.
16.
1// YYYY_MM_DD_XXXXX_create_categories_table.php
2.
3.
4 public function up(): void
5 {
6 Schema::create('categories', function (Blueprint $table) {
7 $table->id();
8 $table->string("name"); // 追加部分
9 $table->timestamps();
10 });
11 }
12.
13.
上記のコードを追加したら、次のコマンドでpostsテーブルとcategoriesテーブルを作成します。
※postsテーブルにcategoriesテーブルのidが外部キーとして設定されているため、先にcategoriesテーブルを作成する必要があります。
1$ sail php artisan migrate --path=/database/migrations/YYYY_MM_DD_XXXXX_create_categories_table.php
2$ sail php artisan migrate --path=/database/migrations/YYYY_MM_DD_XXXXX_create_posts_table.php
続いて、Laravelのセキュリティ機能の1つの一括割り当て保護(Mass Assignment Protection)を全てのモデルから解除します。(今回は説明を簡潔にするため解除しますが、本番運用のアプリケーションで使用する際は適切に設定してあげてください。)
そのために、次のコードをapp/Providers/AppServiceProvider.php の boot() メソッドに追加します。
1// app/Providers/AppServiceProvider.php
2 public function boot(): void
3 {
4 Model::unguard();
5 }
最後にモデル間のリレーションを設定します。
次のようにapp/Models/の中のUser.php、Post.php、Category.phpにコードを追加します。
1// app/Models/User.php
2.
3.
4use Illuminate\Database\Eloquent\Relations\HasMany;
5.
6.
7 public function posts(): HasMany
8 {
9 return $this->hasMany(Post::class);
10 }
11.
12.
1// app/Models/Post.php
2use Illuminate\Database\Eloquent\Factories\HasFactory;
3use Illuminate\Database\Eloquent\Model;
4use Illuminate\Database\Eloquent\Relations\BelongsTo;
5
6class Post extends Model
7{
8 use HasFactory;
9
10 public function user(): BelongsTo
11 {
12 return $this->belongsTo(User::class);
13 }
14
15 public function category(): BelongsTo
16 {
17 return $this->belongsTo(Category::class);
18 }
19}
1// app/Models/Category.php
2use Illuminate\Database\Eloquent\Factories\HasFactory;
3use Illuminate\Database\Eloquent\Model;
4use Illuminate\Database\Eloquent\Relations\HasMany;
5
6class Category extends Model
7{
8 use HasFactory;
9
10 public function posts(): HasMany
11 {
12 return $this->hasMany(Post::class);
13 }
14}
リソースの作成
FilamentのリソースとはCRUDの処理を操作するインターフェイスを構築するために使用される静的クラスことです。
次のコマンドでCategoryモデルとPostモデルのリソースを作成します。
1$ sail php artisan make:filament-resource Category
2$ sail php artisan make:filament-resource Post
上記コマンド実行後、app/Filament/Resourcesディレクトリを見ると下の画像のように、CategoryリソースとPostリソースのいくつかのファイルが作成されます。
ダッシュボードの画面をリロードすると下の画像のように「Categories」と「Posts」のリンクが左側のメニューに追加されます。
Categoriesのリンクをクリックすると下の画像のような画面に遷移します。
カテゴリーの登録をしていないので、「No categories」という表示がされます。
フォームの作成
では、カテゴリーを登録できるように実装していきます。
app/Filament/ResourcesディレクトリにあるCategoryResource.phpを次のように修正します。
1// app/Filament/Resources/CategoryResource.php
2.
3.
4 public static function form(Form $form): Form
5 {
6 return $form
7 ->schema([
8 Forms\Components\TextInput::make('name') // 修正部分
9 ->required() // 修正部分
10 ->maxLength(255) // 修正部分
11 ]);
12 }
13.
14.
Categories画面の右上にある「New category」ボタンを押すと、下の画像のように、カテゴリー名の入力欄が追加されます。
ここで、Nameの入力欄に「PHP」と入力してカテゴリーを登録してみます。
しかし、Categories画面をみても「PHP」の表示がありません。
登録したデータを表示できるようにしていきます。
テーブルの作成
app/Filament/ResourcesディレクトリにあるCategoryResource.phpを次のように修正します。
1// app/Filament/Resources/CategoryResource.php
2.
3.
4 public static function table(Table $table): Table
5 {
6 return $table
7 ->columns([
8 Tables\Columns\TextColumn::make('name') // 修正部分
9 ])
10.
11.
Categories画面をリロードすると下の画像のようにCategoryのnameが表示されるようになります。
では下の画像のように別のカテゴリーも登録してみます。
「Java」と「MySQL」というカテゴリーを追加してみました。
では、このような管理画面でよくある機能の「検索機能」と「ソート機能」を実装していきたいと思います。
CategoryResource.phpを次のようにコードを追加します。
1// app/Filament/Resources/CategoryResource.php
2.
3.
4 public static function table(Table $table): Table
5 {
6 return $table
7 ->columns([
8 Tables\Columns\TextColumn::make('name')
9 ->searchable() // 追加部分
10 ->sortable(), // 追加部分
11 ])
12.
13.
画面をリロードすると下の画像のように、右上に検索ボックスとNameの右横に矢印が追加されるのがわかります。
Postのフォームとテーブルを作成
では、PostでもCategoryと同じようにフォームとテーブルを作成します。
コードを次のように変更します。
1// app/Filament/Resources/PostResource.php
2.
3.
4 public static function form(Form $form): Form
5 {
6 return $form
7 ->schema([
8 Forms\Components\TextInput::make('title')
9 ->required()
10 ->maxLength(255),
11 Forms\Components\Select::make('user_id')
12 ->relationship(name: 'user', titleAttribute: 'name'),
13 Forms\Components\Select::make('category_id')
14 ->relationship(name: 'category', titleAttribute: 'name'),
15 Forms\Components\RichEditor::make('content')
16 ->columnSpanFull(),
17
18 ]);
19 }
20
21 public static function table(Table $table): Table
22 {
23 return $table
24 ->columns([
25 Tables\Columns\TextColumn::make('title')
26 ->searchable()
27 ->sortable(),
28 Tables\Columns\TextColumn::make('user.name')
29 ->searchable()
30 ->sortable(),
31 Tables\Columns\TextColumn::make('category.name')
32 ->searchable()
33 ->sortable(),
34 ])
35 }
36.
37.
上記コードで新しく出てきてコードを簡単に説明します。
relationship(name: 'user', titleAttribute: 'name')
relationship()メソッドは、ModelでBelongsToの関係を設定した値を自動的にformのoption要素として取得することができます。name引数はモデル内の関係を定義するもの、titleAttribute引数は関連するテーブルから使用する列名です。(上記の場合、Userモデルのnameカラムの値をoption要素に取得してくることになります)
Filament\Forms\Components\RichEditor
HTMLのコンテンツを編集およびプレビューしたり、画像をアップロードしたりできるフィールドを作れます。
columnSpanFull()
設定したフィールドをの幅を親要素の幅まで広げるメソッドです。
上記コードの修正を行ったら画面をリロードして、投稿を作ってみます。
Postsの一覧画面からNew postボタンをクリックすると下の画像のような画面になります。
下の画像のように「Javaの勉強法」という仮のPostを作ってみました。(※文章はChatGPTに適当に出してもらったものです)
これで簡易的なブログ投稿ができる管理画面が完成です。
おわりに
簡易的ではあるものの、想像以上のスピードでいい感じの管理画面が作れて驚きました。
公式のドキュメントがかなり充実していそうなので(全部は見切れていない)機会があれば他の機能も試したいと思います!
参照URL
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
フロントエンジニアの森屋敏です! ドラム叩くのが好き。