Filamentを使えばLaravelアプリケーションの管理画面が簡単に作成可能
Laravelを利用して簡単にダッシュボードやアプリケーションを構築したいと思ったことはありませんか?そんな人にお勧めなのがFilamentです。Laravelを使ってAdmin Panel(管理画面)を持つアプリケーション(CMS:Content Management System)をこれから構築する予定がある人なら一度はどのようなものか体験してほしいパッケージです。日本語化にも対応しています。
本文書ではFilamentがどういうものなのかすぐに理解してもらうため前半ではデフォルトのUserモデルを利用して動作確認を行っています。Userモデルを管理する画面なら驚きの速さで作成、カスタマイズ可能です。Laravel Filamentをうまく活用できればアプリケーションの開発を効率よく高速に行えることを確認してもらえます。
目次
Filamentとは
FilamentはTALL(Tailwind CSS, Alpine.js, Laravel, Livewire) Stackで構築されたパッケージで認証機能を持ち、ダッシュボードからフォーム、テーブル、通知までアプリケーションに必須な機能を備えています。細かなカスタマイズを行えるだけではなく100を超えるプラグインを利用して機能の拡張を行うことができます。TALL Stackを構成する技術の理解がなくても簡単なアプリであれば数分で作成することができます。活発に開発が行われており現在はバージョン3です。Laravelのバージョン10から対応しています。
Filamentのドキュメントを見ると”Panel Builder”, “Form Builder”, “Table Builder”, “Notifications”, “Actions”, “Infolist Builder”, “Widgets”に分かれています。それぞれ独立した機能として個別にインストールを行うことができますがAdmin Panel(管理画面)に関連するPanel Builderをインストールするとそのほかの機能を利用するためすべてのパッケージがインストールされます。FilamentをAdmin Panelとして利用するだけではなく、”Form Builder”, “Table Builder”など”Panel Builder”以外の機能をLivewireと一緒に利用することでLaravelのアプリケーション開発を効率化することができます。
環境の構築
プロジェクトの作成
Laravel Filamentの動作確認を行うためにLaravelプロジェクトの作成を行います。Laravel11の場合はプロジェクト作成時にデータベースの設定まで行ってくれます。
% composer create-project laravel/laravel laravel_filament
データベースの作成
Laravel11ではプロジェクト作成時にすでに完了しています。
本文書ではデータベースにSQLiteを利用します。.envファイルのDB_CONNECTIONの値をデフォルトのmysqlからsqliteに変更してそのほかのDB_の付いた環境変数を削除します。
php artisan migrateコマンドを実行してテーブルを作成します。SQLiteはファイルベースのデータベースなのでファイルが必要ですが作成していない場合はphp artisan migrateコマンドを実行すると作成するか聞かれるので”Yes”を選択してください。
Laravel Filamentの初期設定
Filamentパッケージのインストールを行います。
% composer require filament/filament:"^3.2" -W
Filamentをインストール後はPanel Builderのインストールを行います。名前にPanelが入っている通りAdmin Panelを作成するために利用する機能です。
Panel Builderのインストールを行うとIDを聞かれるのでadminに設定しておきます。
% php artisan filament:install --panels
┌ What is the ID? ─────────────────────────────────────────────┐
│ admin │
└──────────────────────────────────────────────────────────────┘
php artisan serveコマンドを実行します。
% php artisan serve
INFO Server running on [http://127.0.0.1:8000].
Press Ctrl+C to stop the server
ブラウザからhttp://127.0.0.1/adminにアクセスすると/admin/loginにリダイレクトされてログイン画面が表示されます。
Admin Panelにアクセスするためにはユーザの作成が必要です。ユーザの作成はコマンドで行うことができます。
% php artisan make:filament-user
┌ Name ────────────────────────────────────────────────────────┐
│ John Doe │
└──────────────────────────────────────────────────────────────┘
┌ Email address ───────────────────────────────────────────────┐
│ john@example.com │
└──────────────────────────────────────────────────────────────┘
┌ Password ────────────────────────────────────────────────────┐
│ •••••••• │
└──────────────────────────────────────────────────────────────┘
INFO Success! john@example.com may now log in at http://laravel_filament.test/admin/login.
作成したユーザでログイン画面からログインするとAdmin PanelのDashboardページが表示されます。
右上のボタンをクリックするとダークモードに変更することもできます。
さらにResponsive Designにも対応しているのでブラウザの幅を狭くすると表示デザインがかわります。
文字や背景の色も簡単に変更することができます。詳細はhttps://filamentphp.com/docs/3.x/panels/themesを確認でき、変更はFilamentのServiceProviderファイルであるAdminPanelProvider.phpファイルで変更可能です。
Resource
Resourceの作成
既存のUserモデルをAdmin Panelに表示させるためにresourcesを作成する必要があります。resourcesはUserモデルをCRUD(Create, Read , Update, Delete)するために必要なファイルです。作成することでAdmin Panel上にユーザメニューやユーザ一覧を表示できるようになります。
% php artisan make:filament-resource User --generate
INFO Filament resource [app/Filament/Resources/UserResource.php] created successfully.
コマンドを実行後にPanelにアクセスを行うとサイドバーにUsersが追加されクリックするとユーザ一覧のテーブルが表示されます。
“New user”ボタンをクリックするとUserモデルのファイルを元にフォームも作成されます。
ユーザを作成することも可能です。
デフォルトにあるUsersモデルを利用してコマンド一つでResourceを作成すればUser情報を管理するためのアプリケーションの作成は完了です。
Resourceファイルの確認
簡単なカスタマイズ
“php artisan make:filament-resource User –generate”を実行するとapp¥Filament¥Resourcesディレクトリの下にUserResource.phpファイルが作成されます。このファイルによってフォームの設定やテーブルの列についての設定が行われています。
UserResource.phpファイルの中にはform, table, getRelations, getPages関数が存在しますがテーブルに関する設定はtable関数で行われています。UserResource.phpファイルでさまざまなカスタマイズを行うことができます。
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name')
->searchable(),
Tables\Columns\TextColumn::make('email')
->searchable(),
Tables\Columns\TextColumn::make('email_verified_at')
->dateTime()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
例えばユーザ一覧のテーブルでnameとemailのみ表示させたい場合は下記のように書き換えることで実現できます。
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name')
->searchable(),
Tables\Columns\TextColumn::make('email')
->searchable(),
// Tables\Columns\TextColumn::make('email_verified_at')
// ->dateTime()
// ->sortable(),
// Tables\Columns\TextColumn::make('created_at')
// ->dateTime()
// ->sortable()
// ->toggleable(isToggledHiddenByDefault: true),
// Tables\Columns\TextColumn::make('updated_at')
// ->dateTime()
// ->sortable()
// ->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
ブラウザで確認するとName, Emailのみ表示されるようになります。
新しいユーザをAdmin Panelから作成させないようにするためにはUserResource/Pages/ListUsers.phpファイルのgetHeaderActions関数を削除することで”New user”ボタンが表示されなくなります。
namespace App\Filament\Resources\UserResource\Pages;
use App\Filament\Resources\UserResource;
// use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListUsers extends ListRecords
{
protected static string $resource = UserResource::class;
// protected function getHeaderActions(): array
// {
// return [
// Actions\CreateAction::make(),
// ];
// }
}
“Edit”のリンクをクリックするとName, Email, Email verified at, Passwordのinput要素が表示されますがNameのみ更新可能としたい場合はUserResource.phpのform関数でForms\Components\TextInput::make(‘name’)のみ残します。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->required(),
// Forms\Components\TextInput::make('email')
// ->email()
// ->required(),
// Forms\Components\DateTimePicker::make('email_verified_at'),
// Forms\Components\TextInput::make('password')
// ->password()
// ->required(),
]);
}
更新画面ではNameのinput要素のみ表示されるようになります。
このように簡単にカスタマイズを行うことができます。
自動ページリフレッシュ
app¥Filament以下のリソースファイルを更新後毎回ブラウザの再読み込みを手動で行うのは開発効率が悪いので自動でページのリフレッシュが行えるように設定を行います。
app¥Filamentディレクトリ以下のファイルを更新すると自動でページのリフレッシュが行われるようにvite.config.jsファイルの更新を行います。
import { defineConfig } from "vite";
import laravel, { refreshPaths } from "laravel-vite-plugin";
export default defineConfig({
plugins: [
laravel({
input: ["resources/css/app.css", "resources/js/app.js"],
refresh: [...refreshPaths, "app/Livewire/**", "app/Filament/**"],
}),
],
});
これだけの設定では自動でページリフレッシュは行われません。npm installコマンドを実行してJavaScriptライブラリのダウンロードを行い、npm run devコマンドでビルドを行います。ビルドを行った後に作成されるapp.jsファイルが読み込まれるようにAdminPanelProvier.phpファイルにregister関数を追加します。
public function register():void
{
parent::register();
FilamentView::registerRenderHook('panels::body.end',fn():string => Blade::render("@vite('resources/js/app.js')"));
}
register関数の中ではregisterRenderHookを利用してAdmin Panelsが利用するLayoutファイルのbodyの閉じタグの前にresource/js/app.jsファイルを読み込んでいます。
ブラウザ上でページのソースを確認するとbodyの閉じタグの前に下記のコードが追加されます。
<script type="module" src="http://127.0.0.1:5173/@vite/client" data-navigate-track="reload"></script><script type="module" src="http://127.0.0.1:5173/resources/js/app.js" data-navigate-track="reload"></script>
日本語化設定
Admin Panelsの日本語化設定
Admin Panelsの画面はすべて英語で表示されていましたがapp.phpファイルでlocaleの値をデフォルトの’en’から’ja’に変更することで日本語化することができます。
'locale' => 'ja',
設定後ダッシュボードのページにアクセスするとメニューもDashboardからダッシュボードに変わっていることが確認できます。
Userページにアクセスするとボタンなども日本語化されていることが確認できます。
日本語化された内容を変更したい場合には言語ファイルを利用して変更することができます。
% php artisan vendor:publish --tag=filament-panels-translations
INFO Publishing [filament-panels-translations] assets.
Copying directory [vendor/filament/filament/resources/lang] to [lang/vendor/filament-panels] .. DONE
lang¥vendor¥filament-panelsディレクトリが作成され、その下にjaディレクトリが作成されるのでその下にファイルの内容を更新することで表示されている日本語を変更することができます。
モデル名の日本語化設定
Admin PanelsのサイドバーのメニューではDashboardはダッシュボードに変わりましたがUserは英語のままです。UserページのタイトルもUserのままです。Userをユーザに変更する方法を確認します。
FilamentのUserResource.phpファイルで$modelLabelの設定を行います。
class UserResource extends Resource
{
protected static ?string $model = User::class;
protected static ?string $modelLabel = 'ユーザ';
//略
設定後Userページを確認するとUserからユーザに変更になっています。
テーブルの列名の日本語化
Userページの中で列名のNameとEmailが英語で表示されています。列の名前によっては日本語に変更する必要はありませんが日本語にしたい場合にはUserResource.phpファイルで行います。labelメソッドを追加して引数に対応する日本語を設定します。
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name')
->label('名前')
->searchable(),
Tables\Columns\TextColumn::make('email')
->label('メールアドレス')
->searchable(),
設定後はUserページ全体が日本語化されていることが確認できます。
フォームの基礎
モデルの作成
フォームの理解を深めるために新たにCategoryモデルの作成を行います。
% php artisan make:model Category -m
INFO Model [app/Models/Category.php] created successfully.
INFO Migration [database/migrations/2024_01_30_130006_create_categories_table.php] created successfully.
app/ModelsディレクトリにCategory.phpファイル、migrationsディレクトリにマイグレーションファイルが作成されます。マイグレーションファイルにname列を追加します。
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table-'>timestamps();
});
}
name列を追加後”php artisan migrate”コマンドを実行します。データベースにはcategoriesテーブルが追加されます。
Resourceの作成
作成したCategoryモデルのResourcesの作成を行います。
% php artisan make:filament-resource Category --generate
INFO Filament resource [app/Filament/Resources/CategoryResource.php] created successfully.
Admin PanelsにアクセスするとCategoriesが追加されていることが確認できます。
Categoryの文字列を日本語化します。CategoryResource.phpファイルで設定します。
protected static ?string $modelLabel = 'カテゴリー';
Mass Assignments
新規のカテゴリーを追加するために”作成”ボタンをクリックします。カテゴリーの作成画面が表示されるのでNameに文字列を入力して”作成”ボタンをクリックします。
クリックするとIlluminate \ Database \ Eloquent \ MassAssignmentExceptionエラーが発生します。メッセージにあるように問題は回避するためにCategory.phpファイルに$fillableを追加する必要があります。
Add [name] to fillable property to allow mass assignment on [App\Models\Category].
app¥Models¥Category.phpファイルに$fillableを下記のように追加することでエラーは消えます。
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
protected $fillable = [
'name',
];
}
各モデルファイルでの$fillableの設定ではくapp/Providers/AppServiceProvider.phpのファイルの中でも”mass assignments protection”を無効にすることができます。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Model;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Model::unguard();
}
}
設定後再度カテゴリーの作成を行うと問題は解消してカテゴリーを追加することができます。
入力要素のカスタマイズ
カテゴリーの作成画面に戻り入力要素のカスタマイズを行っていきます。ここでの設定はinput要素に限定した設定ではなく他の要素でも利用することができます。後ほどinput要素自身の設定について説明を行っています。
Nameの文字列を名前に変更します。CategoryResource.phpファイルのform関数の中でlabelメソッドを追加して引数に”名前”を設定します。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->label('名前')
->required(),
]);
}
labelだけではなくplaceholderや入力の説明文なでもメソッドを利用して追加することができます。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->label('名前')
->placeholder('カテゴリー名')
->helperText('カテゴリー名を入力してください')
->required(),
]);
}
その他の設定はhttps://filamentphp.com/docs/3.x/forms/fields/getting-startedで確認できます。
TextInputの設定
input要素はTextInputコンポーネントのmakeメソッドにテーブルの列名を指定するだけで作成することができます。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name'),
]);
}
requiredメソッドを追加するだけでinput要素にrequired属性が設定されlabelの右側に*(アスタリスク)が表示されます。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->required(),
]);
}
requiredを設定することでブラウザのrequired属性が有効になり、何も入力せず”作成”ボタンをクリックすると”このフィールドを入力してください”というメッセージが表示されます。
そのほかにもemail, password, numericなどのメソッドを利用してブラウザ自身が持つフォームバリデーション機能を利用することができます。TextInputメソッドがどのようなメソッドを持つのかはドキュメント以外ではvendor¥flilament¥forms¥src¥Components¥TextInput.phpファイルで確認できます。
作成後のリダイレクト
カテゴリーを作成するとデフォルトでは右上にメッセージが表示され更新ページにリダイレクトされます。更新ページではなく一覧ページにリダイレクトさせたい場合にはCategoryResource¥Pages¥CreateCategory.phpファイルにgetRedirectUrl関数を追加します。
namespace App\Filament\Resources\CategoryResource\Pages;
use App\Filament\Resources\CategoryResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateCategory extends CreateRecord
{
protected static string $resource = CategoryResource::class;
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
}
Laravelのバリデーションルール設定
ブラウザ自身が持つフォームバリデーションだけではなくLaravelのバリデーションルールの設定方法を確認します。requiredルールであれば下記のように指定することができます。requiredメソッドを設定しているとブラウザ側のバリデーションが先に実行されるので動作確認のためにrequiredメソッドは削除しておきます。通常はブラウザのバリデーションも設定しておきます。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->rules('required'),
]);
}
バリデーションに失敗した場合にはメッセージがinput要素の下に表示されます。
メッセージが英語で表示されています。バリデーションメッセージはFilamentの設定ではなくLaravelのバリデーションメッセージの日本語化で対応します。
日本語化
lang¥jaディレクトリの下にvalidation.phpファイルが必要になりますがデフォルトでは存在しないのでphp artisanコマンドで作成します。
% php artisan lang:publish
INFO Language files published successfully.
実行するとlang¥enディレクトリが作成されその下にauth.php, pagination.php, passwords.php, validataion.phpファイルが作成されます。enディレクトリの名前をjaに変更します。jaディレクトリのvalidation.phpファイルを開いてrequiredの値を日本語に変更します。:attributeはそのままです。
'required' => ':attribute フィールドは必須の項目です',
labelメソッドには名前を設定します。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->rules('required')
->label('名前'),
]);
}
再度バリデーションを実行すると日本語化されていることがわかります。
Relationship
モデル間でRelationshipを持っている場合のフォームの設定について確認していきます。
モデルの作成
新たにFrameworkモデルを追加します。
% php artisan make:model -m Framework
INFO Model [app/Models/Framework.php] created successfully.
INFO Migration [database/migrations/2024_01_31_054919_create_frameworks_table.php] created successfully.
FrameworkはCategoryとRelationshipを持たせるためmigrationファイルでは以下のように設定します。
public function up(): void
{
Schema::create('frameworks', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description')->nullable();
$table->foreignId('category_id')->constrained();
$table->timestamps();
});
}
設定後はphp artisan migrateコマンドを実行してframeworksテーブルを作成します。
Category.phpとFramework.phpファイルにRelationShipsを定義します。Category.phpでhasMany, Framework.phpでbelongsToを設定しています。
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Category extends Model
{
use HasFactory;
public function frameworks(): HasMany
{
return $this->hasMany(Framework::class);
}
}
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Framework extends Model
{
use HasFactory;
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
}
Resourceの作成
作成したFrameworkモデルのResourcesの作成を行います。
% php artisan make:filament-resource Framework --generate
作成されたFrameworkResource.phpファイルで$modelLabelの設定を行います。
protected static ?string $modelLabel = 'フレームワーク';
Admin Panelsにアクセスするとフレームワークが追加されます。
フレークワークを追加するために”作成”ボタンをクリックします。デフォルトではCategory Idは手動で入力する必要があります。
Selectの設定
input要素ではくselect要素によってCategoryIdが設定できるように変更を行います。TextInputコンポーネントからSelectコンポーネントに変更を行います。relationshipのnameにはFramework.phpファイルで設定したRelationshipsの名前を設定します。titleAttributeにはCategoryモデルのnameを指定しています。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('category_id')
->relationship(name: 'category', titleAttribute: 'name'),
Forms\Components\TextInput::make('name')
->required(),
Forms\Components\Textarea::make('description')
->columnSpanFull(),
]);
}
ブラウザで確認するとinput要素からselect要素に変わり、プルダウンメニューでCategoryを選択できるようになります。
“JavaScript”を選択してフレームワークを作成後に一覧を確認します。Category idには選択したJavaScriptのidの1が表示されています。
Category idではなくCategoryの名前が表示されるようにFrameworkResource.phpファイルのtable関数を変更します。デフォルトではTextColumn::makeの引数にはcategory_idが設定されていましたがcategory.nameに変更しています。
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('category.name'),
Tables\Columns\TextColumn::make('name')
->searchable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
//略
}
idからカテゴリーの名前に変わっていることが確認できます。
リレーションを持つモデルでも簡単にフォームを作成することができます。
メニューへの新しいデータの追加
Selectのプルダウンメニューの中に選択したい項目がない場合に項目を追加することができます。
createOptionFormメソッドを追加します。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('category_id')
->relationship(name: 'category', titleAttribute: 'name')
->createOptionForm([
Forms\Components\TextInput::make('name')
->label('カテゴリー名')
->required(),
]),
Forms\Components\TextInput::make('name')
->required(),
Forms\Components\RichEditor::make('description')
->columnSpanFull(),
]);
}
設定後はselect要素の右側に”+”が表示されます。
“+”ボタンをクリックするとModalが表示されカテゴリーを追加することができます。追加したカテゴリーはプロダウンメニューに追加され選択することができます。
selectの選択項目の更新
createOptionFormメソッドを利用することでメニューの項目を増やすことができました。editOptionFormメソッドを利用するとメニューの編集を行うことができます。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('category_id')
->relationship(name: 'category', titleAttribute: 'name')
->createOptionForm([
Forms\Components\TextInput::make('name')
->label('カテゴリー名')
->required(),
])
->editOptionForm([
Forms\Components\TextInput::make('name')
->label('カテゴリー名')
->required(),
]),
Forms\Components\TextInput::make('name')
->required(),
Forms\Components\RichEditor::make('description')
->columnSpanFull(),
]);
}
プルダウンメニューから選択を行うと編集のアイコンが表示されます。
アイコンをクリックすると編集画面がModalで表示され編集を行うことができます。
フォームの基礎(2)
Rich Editor
FrameworkのdescriptionについてはTextareaコンポーネントを利用していましたがRich Editorを利用することができます。設定はTextareaコンポーネントををRichEditorコンポーネントに変更するだけです。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('category_id')
->relationship(name: 'category', titleAttribute: 'name'),
Forms\Components\TextInput::make('name')
->required(),
Forms\Components\RichEditor::make('description')
->columnSpanFull(),
]);
}
RichEditor設定後の作成画面は文字の太さやリスト表示などで記述することができます。
Rich Editorを利用して一部の文字を太文字に設定します。
Tableの表示設定
descriptionはフレームワークの一覧ページでは見表示に設定が行われていないので表示されるようにFrameworkResource.phpファイルのtable関数で設定を行います。
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('category.name'),
Tables\Columns\TextColumn::make('name')
->searchable(),
Tables\Columns\TextColumn::make('description'),
//略
設定後確認するとRich Editorで記述したdescriptionはHTMLタグを含んで登録されていることがわかります。
HTMLとして表示させたい場合にはhtmlメソッドを利用します。
Tables\Columns\TextColumn::make('description')
->html(),
descriptionの文字列が長い場合はlimitメソッドやwordメソッドを利用して表示させる長さを調整することができます。
Tables\Columns\TextColumn::make('description')
->limit(20),
descriptionメソッド
Category列にdescriptionを一緒に表示させることもできます。descriptionという列名とdescriptionメソッドと同じ名前なので混乱するかもしれませんが下記のようにdescriptionメソッドを利用します。ここではたまたまdescription列をClousureの戻り値に設定していますがidやnameを戻すこともできます。
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('category.name')
->description(function(Framework $record):string{
return $record->description;
}),
デフォルトでは下に表示されます。
上に表示させたい場合はdescriptionの第二引数のpositionの値を’above’にします。デフォルトは’below’です。
Modalによるフォーム表示
カテゴリーのように入力項目が少ない場合には作成画面に移動してフォームに入力するのではなくModalを利用することができます。
CategoryResource.phpファイルのgetPages関数のcreateの1行をコメントします。
//略
public static function getPages(): array
{
return [
'index' => Pages\ListCategories::route('/'),
// 'create' => Pages\CreateCategory::route('/create'),
'edit' => Pages\EditCategory::route('/{record}/edit'),
];
}
作成画面ではなくModal上にフォームが表示されカテゴリーを追加することができます。
Slide Overによるフォームの表示
Modalによるフォーム設定では作成画面をModal表示にしましたが同様の方法で編集画面もModal表示にすることができます。
//略
public static function getPages(): array
{
return [
'index' => Pages\ListCategories::route('/'),
// 'create' => Pages\CreateCategory::route('/create'),
// 'edit' => Pages\EditCategory::route('/{record}/edit'),
];
}
ModalではなくSlide Overのフォームも利用することができます。
public static function table(Table $table): Table
{
return $table
->columns([
//略
->actions([
Tables\Actions\EditAction::make()->slideOver(),
])
//略
}
設定後編集ボタンをクリックすると右側からSlideしてフォームが表示されます。
ファイルのアップロード
フォームからのファイルのアップロードについて確認していくためFrameworkモデルのスキーマに追加設定を行います。migrationファイルにアップロードしたファイルのパスを保存するためのimage列を追加します。
public function up(): void
{
Schema::create('frameworks', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('image')->nullable();
$table->text('description')->nullable();
$table->foreignId('category_id')->constrained();
$table->timestamps();
});
}
frameworksテーブルを再作成するためにphp artisan migrate:rollbackを行い、再度php artisan migrateコマンドを実行します。
アップロードしたファイルはデフォルトではstorage/app/publicディレクトリに保存されます。外部に保存した画像を表示できるように”php artisan storage:link”コマンドを実行してpublicディレクトリにシンボリックリンクを貼ります。
% php artisan storage:link
INFO The [public/storage] link has been connected to [storage/app/public].
FrameworkResource.phpファイルのform関数にFileUploadコンポーネントを利用してフォームにファイルをアップロードするためのフィールドを追加します。
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('category_id')
->relationship(name: 'category', titleAttribute: 'name')
->createOptionForm([
Forms\Components\TextInput::make('name')
->label('カテゴリー名')
->required(),
])
->editOptionForm([
Forms\Components\TextInput::make('name')
->label('カテゴリー名')
->required(),
]),
Forms\Components\FileUpload::make('image'), //追加
Forms\Components\TextInput::make('name')
->required(),
Forms\Components\RichEditor::make('description')
->columnSpanFull(),
]);
}
ファイルをDrag&Dropするとプレビューが表示されます。
“作成”ボタンをクリックして保存するとstorage/app/publicディレクトリに01HNH3TM4TA8Z2SMZE4D7CRRDQ.pngという名前のファイルが保存されていることが確認できます。frameworksのimage列にも同じ情報が保存されています。
デフォルトではファイル名にはランダムな名前が設定されるのでアップロードしたファイルの名前のまま保存したい場合にはpreserveFilenamesメソッドを利用することができます。
Forms\Components\FileUpload::make('image')->preserveFilenames()
保存するディレクトリを指定したい場合にはdirectoryメソッドを追加します。
Forms\Components\FileUpload::make('image')->directory('images')->preserveFilenames()
デフォルトではどのようなファイルでも選択してアップロードできるのimageメソッドを追加することで画像ファイルのみアップロード可能となります。その他にも複数ファイルのアップロード、ファイルのサイズの変更等も可能なのでドキュメントを参考にしてください。
ここまでの動作確認を通してTALL Stackの構成するTailwind CSS、 Alpine.js、Livewireについて知らなくてもアプリケーションを構築することができることがわかってもらえたのではないでしょうか。