0
0

More than 3 years have passed since last update.

一つのユーザーテーブルを複数のモデルとガードに分ける

Last updated at Posted at 2021-03-22

背景

ロールを元にユーザーテーブルのガードを分けたかった。

実践的には、ガードを分けるよりも、一つのガードでログインした後に権限でアクセス制御したほうがいいと思う。あくまでも実験的なものとして覚え書きを残す。

動作環境

  • Mac OS X 10.15.7
  • Laravel 8.33.1
  • Laravel Permission 4.0.0

プロジェクトの作成

Laravel-Permission の導入

composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"

モデルの作成

php artisan make:model Student -f
php artisan make:model Teacher -f

app/Models/Student.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Spatie\Permission\Traits\HasRoles;

class Student extends Model
{
    use HasFactory;
    use HasRoles;

    protected $table = 'users';

    protected $fillable = ['name', 'email', 'password'];

    protected $hidden = ['password', 'remember_token'];

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    protected static function booted(): void
    {
        static::creating(function ($student) {
            $student->assignRole('student');
        });

        static::addGlobalScope('role', function (Builder $builder) {
            $builder->role('student');
        });
    }
}

app/Models/Teacher.php

namespace App\Models;

use Spatie\Permission\Traits\HasRoles;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Teacher extends Model
{
    use HasFactory;
    use HasRoles;

    protected $table = 'users';

    protected $fillable = ['name', 'email', 'password'];

    protected $hidden = ['password', 'remember_token'];

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    protected static function booted(): void
    {
        static::creating(function ($teacher) {
            $teacher->assignRole('teacher');
        });

        static::addGlobalScope('role', function (Builder $builder) {
            $builder->role('teacher');
        });
    }
}

User に書いてそれぞれ継承でもいいと思う。

ガードの設定

プロパイダーの設定を auth.providers に追記する。

'students' => [
    'driver' => 'eloquent',
    'model' => App\Models\Student::class,
],
'teachers' => [
    'driver' => 'eloquent',
    'model' => App\Models\Teacher::class,
],

ガードの設定を auth.guards に追記する。

'student' => [
    'driver' => 'session',
    'provider' => 'students',
],
'teacher' => [
    'driver' => 'session',
    'provider' => 'teachers',
],

ファクトリの作成

UserFactorydefinition() をコピーして、StudentFactoryTeacherFactory を用意する。

ロールの投入

マイグレーションして、Role を用意する。

php artisan migrate
php artisan permission:create-role student student
php artisan permission:create-role teacher teacher

動作確認

Tinker で動作確認する。

php artisan tinker

Student, Teacher を作成して、それぞれ別々に取得できるのを確かめる。

Student::factory(3)->create();
Teacher::factory(3)->create();
Student::all();
Teacher::all();

補足:ガードを追加したくない場合

Laravel-Permission はガードに紐づいているプロバイダーの model を元にロールを絞り込む。
ガードを新たに追加しなくても、モデルに public function guardName()protected $guard_name を明示すると特定のガードを流用できる。

この方法を選んだ場合、「ロールの投入」でも第二引数の guard_name を合わせること。

参考資料

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