Laravel-Filament環境構築(認証機能の追加)

情報収集

filamentを利用している人が認証・権限周りで使用しているプラグイン・パッケージなどを調べてみた。

  1. shield
    filament公式ページのプラグイン紹介の中で、人気っぽい。
    「Laravel-permission」上で動くパッケージ
    (公式プラグイン紹介:https://filamentphp.com/plugins/bezhansalleh-shield
  2. FilamentAccessControl
    あまり人気はないけど、日本人の人が解説してくれている。
    「Laravel-permission」上で動くパッケージ(俺の推測)
    解説している人が言っている通り、あまり開発が盛んでないのが懸念。
    (紹介:https://zenn.dev/egstock_inc/articles/8e5ca678e80cf2
  3. filament-spatie-roles-permissions
    あまり人気はないけど、動画の人が、shieldではなくあえてこちらと言っていた。なんで?
    「Laravel-permission」上で動くパッケージ
    (解説動画:https://www.youtube.com/watch?v=bF04VPI68sg
  4. Laravel-permission
    SPATIE(ベルギーの会社・Laravelに貢献しているらしい)が作った。
    filament関係なくした場合Laravelではよく使用する人がいるようで、情報も多い。
    他のパッケージのベースになっていたりする。
    (解説動画:https://www.youtube.com/watch?v=YZRxhR_5OPs

結局、filamentの枠は外して、情報量の多いLaravel-permissionを使ってみることにした。

Laravel-permissionとは

下記の記事が詳しい。

学んだことの忘備録

  • 役割権限機能を実装するに当たって必要になるテーブルや、権限の管理を一括サポートしてくれる。
    • ユーザーに役割を割り当てる(UserとRoleの紐づけ)
    • ユーザーが特定の役割を持っているかどうかのチェック
    • 役割に基づいたアクセス制御の実装
    • 権限の管理(権限の作成、削除、編集など)

Laravel-permissionのインストール

インストール

公式サイトを見ながら作業した。

インストール

composer require spatie/laravel-permission

サービスプロバイダの登録

'providers' => [
    // ...省略
    Spatie\Permission\PermissionServiceProvider::class,
];

設定ファイルとマイグレーションファイルの発行

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"

実行すると以下のファイルが生成される

  • config\permission.php
  • database\migrations\2023_08_07_050405_create_permission_tables.php

マイグレーションの実行

キャッシュをクリアしてからマイグレーションを実行

php artisan config:clear
php artisan migrate

データベースにテーブルが生成される

  • role_has_permissions
  • model_has_roles
  • model_has_permissions
  • roles
  • permissions

Userモデルの編集

// ~~~~~中略~~~~~
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles; // 追加

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, HasRoles; // HasRolesを追記

初期データの作成

seederを使って初期データ(ユーザーとロールと権限)を作成する。

雛形の作成

php artisan make:seeder RolesAndPermissionsSeeder

以下のファイルが生成される

  • database\seeders\RolesAndPermissionsSeeder.php

シーダーファイルの編集

<?php

namespace Database\Seeders;

use App\Models\User; // 追加

// ~~~~~中略~~~~~

use Illuminate\Support\Facades\Hash; // 追加
use Spatie\Permission\Models\Permission; // 追加
use Spatie\Permission\Models\Role; //追加

// ~~~~~中略~~~~~

class RolesAndPermissionsSeeder extends Seeder
{
    /**
     * Run the database seeds.
     * @return void
     */
    public function run(): void
    {
        // 追加
        // adminユーザーを作成
        $adminUser = new User();
        $adminUser->name = '管理者(admin)';
        $adminUser->email = 'admin@pasocafe.jp';
        $adminUser->password = Hash::make('password');
        $adminUser->save();

        // gamerユーザーを作成
        $gamerUser01 = new User();
        $gamerUser01->name = 'ゲーマー01(gamer)';
        $gamerUser01->email = 'gamer01@pasocafe.jp';
        $gamerUser01->password = Hash::make('password');
        $gamerUser01->save();

        $gamerUser02 = new User();
        $gamerUser02->name = 'ゲーマー02(gamer)';
        $gamerUser02->email = 'gamer02@pasocafe.jp';
        $gamerUser02->password = Hash::make('password');
        $gamerUser02->save();

        // Roleの作成
        $admin = Role::create(['name' => 'admin']);
        $editor = Role::create(['name' => 'gamer']);

        // Permissionの作成
        $permissionOfLoginAdminPanel = Permission::create(['name' => 'login AdminPanel']);

        // RoleとPermissionを関連付け
        $admin->givePermissionTo($permissionOfLoginAdminPanel);

        // UserにRoleを割り当て
        $adminUser->assignRole('admin');
        $gamerUser01->assignRole('gamer');
        $gamerUser02->assignRole('gamer');
    }
}

シーダーファイルの実行

php artisan db:seed --class=RolesAndPermissionsSeeder

DBにユーザーやロールが作成される。

管理画面に編集画面を追加

roleやpermissionを管理画面で編集できるようにresourceを追加してみよう。以下の動画を参考にした。

roleリソース

こちらは丁寧に作ってみる。雛形の作成で–generateを使用しないため、自分で雛形を修正する必要が出る。

雛形の作成

php artisan make:filament-resource Role

以下のファイルが生成される

  • app\Filament\Resources\RoleResource.php
  • app\Filament\Resources\RoleResource\Pages\CreateRole.php
  • app\Filament\Resources\RoleResource\Pages\EditRole.php
  • app\Filament\Resources\RoleResource\Pages\ListRoles.php

⚠4つ生成されない場合は–generateオプションを付ける。

RoleResource.phpの編集

// ~~~~~中略~~~~~
// use App\Models\Role; // コメントアウト
// ~~~~~中略~~~~~
use Spatie\Permission\Models\Role; // 追加

class RoleResource extends Resource
{
    protected static ?string $model = Role::class; // 変更
    protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
    protected static ?string $modelLabel = 'ロール'; // 追加
    protected static ?string $navigationGroup = '管理'; // 追加

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                // 追加
                Forms\Components\TextInput::make('name')
                    ->minLength(2)
                    ->maxLength(255)
                    ->required()
                    ->unique(ignoreRecord: true)
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                // 追加
                Tables\Columns\TextColumn::make('name')->label('名前'),
            ])

データ作成時のリダイレクト先変更

class CreatePost extends CreateRecord
{

    // ~~~~~中略~~~~~
    // 完了後にリストに戻る
    protected function getRedirectUrl(): string
    {
        return $this->getResource()::getUrl('index');
    }

permissionリソース

雛形の作成

php artisan make:filament-resource Permission

以下のファイルが生成される

  • app\Filament\Resources\PermissionResource.php
  • app\Filament\Resources\PermissionResource\Pages\CreatePermission.php
  • app\Filament\Resources\PermissionResource\Pages\EditPermission.php
  • app\Filament\Resources\PermissionResource\Pages\ListPermission.php

PermissionResource.phpの編集

// ~~~~~中略~~~~~
// use App\Models\Role; // コメントアウト
// ~~~~~中略~~~~~
use Filament\Forms\Components\Card; // 追加
// ~~~~~中略~~~~~
use Spatie\Permission\Models\Permission; // 追加

class RoleResource extends Resource
{
    protected static ?string $model = Permission::class; // 変更
    protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
    protected static ?string $modelLabel = 'パーミッション'; // 追加
    protected static ?string $navigationGroup = '管理'; // 追加

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                // 追加
                Card::make()->schema([
                    Forms\Components\TextInput::make('name')
                        ->minLength(2)
                        ->maxLength(255)
                        ->required()
                        ->unique(ignoreRecord: true)
                ])
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                // 追加
                Tables\Columns\TextColumn::make('name')->label('名前'),
            ])

データ作成時のリダイレクト先変更

class CreatePost extends CreateRecord
{

    // ~~~~~中略~~~~~
    // 完了後にリストに戻る
    protected function getRedirectUrl(): string
    {
        return $this->getResource()::getUrl('index');
    }

Userの修正

UserResource.phpの編集

// ~~~~~中略~~~~~
use Filament\Forms\Components\Card; // 追加
// ~~~~~中略~~~~~

    public static function form(Form $form): Form
    {
        // 全てのギルドを取得
        $guilds = Guild::all()->pluck('name', 'id')->toArray();

        return $form
            ->schema([
                Card::make()->schema([ // 変更:カードで括る start
                // ~~~~~中略~~~~~
                ])->columns(2) // 変更:カードで括る end
            ]);

roleの修正

RoleResource.phpの編集

// ~~~~~中略~~~~~
use Filament\Forms\Components\Card; // 追加
// ~~~~~中略~~~~~

class RoleResource extends Resource
{

    // ~~~~~中略~~~~~

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Card::make()->schema([ // 変更:カードで括る start
                // ~~~~~中略~~~~~
                ]) // 変更:カードで括る end
            ]);
    }

アクセス制限の実装(チュートリアル)

ダッシュボードで実験してみよう

以下の公式ドキュメントを見ながらやってみた

元々のダッシュボードのファイルは下記と思われる。これを変更してはいけない。あくまでも自作のダッシュボードの参考にする。

  • vendor\filament\filament\src\Pages\Dashboard.php
  • vendor\filament\filament\resources\views\pages\dashboard.blade.php

ページの生成

php artisan make:filament-page AdminDashboard

途中、質問が来るが、Enterを押して無視。

途中、質問が来るが、「UserResource」、「View」と答えた。

 (Optional) Resource (e.g. `UserResource`):
 > UserResource

 Which type of page would you like to create? [Custom]:
  [custom       ] Custom
  [ListRecords  ] List
  [CreateRecord ] Create
  [EditRecord   ] Edit
  [ViewRecord   ] View
  [ManageRecords] Manage
 > View

Successfully created AdminDashboard!
Make sure to register the page in `UserResource::getPages()`.

以下のファイルが生成される

  • app\Filament\Pages\AdminDashboard.php
  • resources\views\filament\pages\admin-dashboard.blade.php

ページファイルの修正

公式の以下のページにヒントがあった。

https://filamentphp.com/docs/2.x/admin/dashboard/getting-started#customizing-the-dashboard-page

<?php

namespace App\Filament\Pages;

use Filament\Pages\Dashboard as BasePage;

class AdminDashboard extends BasePage
{
    protected static ?string $navigationIcon = 'heroicon-o-document-text';

    protected static string $view = 'filament.pages.admin-dashboard';

    protected function getWidgets(): array
    {
        // return default widgets
        return Filament::getWidgets();
    }
}

ブレードファイルの修正

<x-filament::page>

</x-filament::page>

↓

<x-filament::page class="filament-dashboard-page">
<x-filament::widgets
        :widgets="$this->getWidgets()"
        :columns="$this->getColumns()"
    />
<h1>これはresources/views/filament/pages/admin-dashboard.blade.phpの内容だよ</h1>
<x-filament::layouts.card title="ようこそ" class="text-center">
    <p>下にメッセージが見れる人はadminだね</p>
    @hasanyrole('admin')
    <p>特別なメッセージだよ</p>
    @endhasanyrole
</x-filament::layouts.card>
</x-filament::page>

コンフィグファイルの生成

コンフィグファイルを使って、標準のダッシュボードをOFFにして自作のダッシュボードが動作するようにする。

⚠コンフィグファイルって元から無いの??下記のコマンドを実行するとコンフィグファイルが生成されるっぽい。

php artisan vendor:publish --tag=filament-config

以下のファイルが生成される

  • config\filament.php

コンフィグファイルの修正

標準のダッシュボード(Pages\Dashboard::class)をコメントアウトする。

⚠自作のダッシュボードを登録するわけではない。コメントアウトすると勝手に自作のダッシュボードになる。

// ~~~~~中略~~~~~
    'pages' => [
        'namespace' => 'App\\Filament\\Pages',
        'path' => app_path('Filament/Pages'),
        'register' => [
            // Pages\Dashboard::class,
        ],
    ],
// ~~~~~中略~~~~~

★★https://laraveldaily.com/post/filament-multiple-dashboards-widgets-user-role

コメントする