💨

Laravel Filamentで請求システム作る No8 ユーザー詳細に配置した権限の一覧の作りこみ

2023/12/10に公開

前回に引き続きFilamentで請求システムを作っていきます

前回は、ユーザー編集画面に権限のテーブルを表示しました。
今回はこれをもうちょっと使いやすくしていきます。

権限名を日本語にする

まずは、権限を日本語化していきます。
現状では、DBに登録されている、「model_name」の値、すなわち英語の文字列が表示されてしまいますが、
これじゃ解りにくいので、英語では無く、日本語で表示します。

要は、model_nameの値を日本語に変換する配列を持ってればOKという事ですね。
今回は、Laravelが元々持っている他言語化の仕組みを利用しようと思います。
「lang\ja\message.php」を作成しました。

lang\ja\message.php
<?php
return [
        'customer' => '顧客',
        'user' => 'ユーザー',
];

また、「app\Filament\Resources\UserResource\RelationManagers\UserHasPolicyRelationManager.php」も変更します。

app\Filament\Resources\UserResource\RelationManagers\UserHasPolicyRelationManager.php
return $table
    ->recordTitleAttribute('権限')
    ->columns([
-        Tables\Columns\TextColumn::make('model_name')->label('機能名'),
+        Tables\Columns\TextColumn::make('jpname')->label('機能名')
+        ->state(function ($record) {
+            //権限名の日本語を返す
+            return \Lang::get("message.{$record->model_name}") . '管理';
    }),

これで、権限名を日本語化する事ができました。

画面表示時に、UserHasPolicyにレコードが無かったら作る

ユーザーの編集画面を開く時に、そのユーザーに紐づくUserHasPolicyのレコードと、「Policies」フォルダ内phpファイルの「$modelName」を比べて、
UserHasPolicyにレコードがなければ、全ての権限をfalseの状態でレコードを作ります。

やる事は以下です。

  1. 「Policies」フォルダ内phpファイルの「$modelName」を全て取ってくる処理を作る
    1. そのためにはprotected $modelNameを取得できるgetModelName関数を
      BasePolicy.phpに作る
  2. ユーザー編集画面で画面描画前に、そのユーザーに紐づくUserHasPolicyのレコードと、①の配列を比較して無いレコードは登録する

となります。

①-1 protected $modelNameを取得できるgetModelName関数をBasePolicy.phpに作る

app\Policies\BasePolicy.php
class BasePolicy
{
    //省略
    protected $modelName = '';

+    public function getModelName()
+    {
+        return $this->modelName;
+    }

① 「Policies」フォルダ内phpファイルの「$modelName」を全て取ってくる処理を作る

UserHasPolicyModelと関わる関数なので、UserHasPolicyServiceを作ってそこに書く事にします。

app\Services\UserHasPolicyService.php
namespace app\Services;

class UserHasPolicyService {
    /**
     * app/Policies/ の中にあるファイルの$modelNameを取得して配列で返す
     *
     * @return array
     */
    public function getAllPolicyModelName()
    {
        $polices = [];
        $policyFiles = \File::files(app_path() . '/Policies');
        foreach ($policyFiles as $file) {
            $name = str_replace('.php', '', $file->getFilename());
            $policyClass = 'App\\Policies\\' . $name;
            $policy = new $policyClass();
            $tPolicy = $policy->getModelName();
            if ($tPolicy != '') {
                $polices[] = $tPolicy;
            }
        }
        return $polices;
    }

とでもする。

②ユーザー編集画面で画面描画前に、そのユーザーに紐づくUserHasPolicyのレコードと、①の配列を比較して無いレコードは登録する

まずは比較して保存する処理

app\Services\UserHasPolicyService.php
//追加する
/**
     * ユーザーにポリシーがなければ作成する
     *
     * @param $userModel    Userモデル
     * @param $polices    システムで利用しているポリシーの配列
     */
    public function compareAndCreateUserPolicies($userModel)
    {
        $polices = $this->getAllPolicyModelName();
        $userId = $userModel->id;
        $hasPolices = $userModel->userHasPolicy()->pluck('model_name')->toArray();
        $saveData = [];
        foreach ($polices as $policy) {
            if (!in_array($policy, $hasPolices)) {
                $saveData[] = [
                    'user_id' => $userId,
                    'model_name' => $policy,
                    'view_any' => 0,
                    'create' => 0,
                    'update' => 0,
                    'delete' => 0,
                    'view' => 0,
                ];
            }
        }
        if (count($saveData) > 0) {
            UserHasPolicy::insert($saveData);
        }
    }

「ユーザー編集画面で画面描画前」に処理を挟みたいので、

app\Filament\Resources\UserResource\Pages\EditUser.php
+ use App\Services\UserHasPolicyService;
class EditUser extends EditRecord
{
    protected static string $resource = UserResource::class;
+    protected function beforeFill()
+    {
+        // システムで利用しているpolicyファイルから、ユーザーの権限を作成する
+        //ユーザーに紐づくUserHasPolicyに内レコードだけ作る
+        $userHasPolicyService = new UserHasPolicyService();
+        // ユーザーにポリシーがなければ作成する
+        $userModel = $this->getRecord()->getModel();
+        $userHasPolicyService->compareAndCreateUserPolicies($userModel);
+    }
     //省略

これで、ユーザーを新規作成後の編集画面への遷移時に、
UserHasPolicyにレコードを作成してくれるようになった。

Discussion