0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravel Filamentでユーザー画面を作ってみた

Last updated at Posted at 2024-10-20

前提

概要

Laravel Filamentは管理画面を簡単に作成できるという記事が多いのですが、通常のユーザー画面も簡単に作れないかと思って試して見ました。

課題

  • アクセスしているユーザーに認可されているデータのみを表示・編集・削除可能とし、それ以外のデータは表示・編集・削除不可とする必要がある。
  • 認可・非認可データの制御やセキュリティ対策はFilament公式ページにも記載されている通り、自己責任でお願いします。

作業

  • 1.ユーザー用パネルのインストール
  • 2.リソース作成
  • 3.リソース/モデル設定

1.ユーザー用パネルのインストール

参考: https://filamentphp.com/docs/3.x/panels/installation

コマンド
./vendor/bin/sail php artisan filament:install --panels
コンソール画面
 ┌ What is the ID? ─────────────────────────────────────────────┐
 │ admin                                                        │
 └──────────────────────────────────────────────────────────────┘

既にadminのIDでパネルをインストールしているので、今回はcustomerとしてインストールしてみました。

コンソール画面
 ┌ What is the ID? ─────────────────────────────────────────────┐
 │ customer                                                     │
 └──────────────────────────────────────────────────────────────┘

ログイン画面が管理者用とユーザー用とで異なる

管理者用ログイン画面(http://localhost/admin/)

login_admin.png

ユーザー用ログイン画面(http://localhost/customer/)

login_customer.png

最初にインストールしたパネルのIDが管理者用、後でインストールしたパネルのIDが通常のログイン画面

2つのパネルのログイン画面が違ったので、Laravelをまっさらな状態にし直し、Filamentのパネルをインストールする際、最初にIDをcustomerとして、2回目のIDをadminとしてインストールしてみたところ、最初にインストールしたIDが管理者用になって、その後でインストールした場合のIDは通常のログイン画面になるようです。

2.リソースの作成

掲示板モデルのリソースを作成します。

コマンド
./vendor/bin/sail php artisan make:filament-resource -G Board
コンソール画面
 ┌ Which panel would you like to create this in? ───────────────┐
 │ › ● admin                                                    │
 │   ○ customer                                                 │
 └──────────────────────────────────────────────────────────────┘

どちらのパネルIDに設定するか聞いてきましたので、customerを選択しました。

管理者パネルにもBoardリソースを作成します。
上と同じコマンドを実行し、adminパネルを選択して作成します。

3.リソース/モデル設定

このままだと、ログインできる全てのユーザーが、自分以外のIDの新規投稿や変更、削除が出来てしまいます。

3.1 画面上に表示されるuser_idを非表示

新規作成画面でuser_idをユーザーが入力できるのは問題ですので非表示にします。
また、一覧画面ではユーザー自身の投稿一覧のみを表示するので、ユーザー名表示を非表示にします。
同様に一覧画面のcreated_at項目とupdated_at項目の表示設定を非表示にします。

app/Filament/Customer/Resource/BoardResource.php(抜粋)
    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                //  Forms\Components\Select::make('user_id')
                //      ->relationship('user', 'name')
                //      ->required(),
                Forms\Components\TextInput::make('title')
                    ->required()
                    ->maxLength(100),
  ・・・
    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                //  Tables\Columns\TextColumn::make('user.name')
                //      ->numeric()
                //      ->sortable(),
                Tables\Columns\TextColumn::make('title')
                    ->searchable(),
                Tables\Columns\TextColumn::make('category')
                    ->searchable(),
                Tables\Columns\TextColumn::make('texts')
                    ->searchable(),
                Tables\Columns\TextColumn::make('date_expiry')
                    ->date()
                    ->sortable(),
                //  Tables\Columns\TextColumn::make('created_at')
                //      ->dateTime()
                //      ->sortable()
                //      ->toggleable(isToggledHiddenByDefault: true),
                //  Tables\Columns\TextColumn::make('updated_at')
                //      ->dateTime()
                //      ->sortable()
                //      ->toggleable(isToggledHiddenByDefault: true),
            ])       

3.2 新規登録/編集時にuser_idを設定

上のままだと、新規登録/編集画面でuser_idの値が入らず、データベースに保存されないので、保存時にuser_idが設定されるようにします。

app/Filament/Customer/Resource/BoardResource/Pages/CreateBoard.php(抜粋)
use Illuminate\Support\Facades\Auth;
class CreateBoard extends CreateRecord
{
    protected static string $resource = BoardResource::class;
    protected function mutateFormDataBeforeCreate(array $data): array
    {
        $data['user_id'] = Auth::id();
        return $data;
    }
}
app/Filament/Customer/Resource/BoardResource/Pages/EditBoard.php(抜粋)
use Illuminate\Support\Facades\Auth;
class EditBoard extends EditRecord
{
    protected static string $resource = BoardResource::class;
    protected function getHeaderActions(): array
    {
        return [
            Actions\DeleteAction::make(),
        ];
    }
    protected function mutateFormDataBeforeFill(array $data): array
    {
        $data['user_id'] = Auth::id();
        return $data;
    }

3.3 一覧画面で自身のデータのみにする設定

現在の状態だと一覧画面で自分以外のデータも表示されてしまうので、自分のデータしかアクセスできないよう設定します。

app/Models/Board.php(抜粋)
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
class Board extends Model
{
    protected static function booted(): void
    {
        static::addGlobalScope('team', function (Builder $query) {
            if (Auth::hasUser()) {
                $query->where('user_id', Auth::user()->id);
            }
        });
    }

上の設定をすると管理者用パネルで問題が起こります。
管理者パネルでは全てのレコードを表示対象にしたいのに、そのようにならなくなります。
そのため管理者パネルでは、モデルに設定されたグローバルスコープを除外するようにします。

app/Filament/Resource/BoardResource.php(抜粋)
    public static function table(Table $table): Table
    {
        return $table
            ->modifyQueryUsing(fn(Builder $query) => $query->withoutGlobalScopes())
            ->columns([
                Tables\Columns\TextColumn::make('user.name')
                    ->numeric()
                    ->sortable(),

ただし、これだと管理者パネルのBoards一覧画面で全てのレコードが表示されますが、ユーザーが作成したレコードに対して編集を行おうとしても編集画面が開きません。

$tableに対してmodifyQueryUsing()を設定するのを元に戻して、BoardResourceに以下の設定をします。

app/Filament/Resource/BoardResource.php(抜粋)
class BoardResource extends Resource
{
  ・・・
    public static function getEloquentQuery(): Builder
    {
        return parent::getEloquentQuery()->withoutGlobalScopes();
    }

以上で、基本的なところは使えそうなユーザー画面になりました。

  • 認可・非認可データの制御やセキュリティ対策は自己責任でお願いします。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?