トップページ
Laravel学習サイトLaravelやるばい

目次

登録ユーザーに権限を追加する

今回から数回の解説に渡りクイズアプリを作っていきます。

解説の回数が多くなるのと実装の難易度が上がっていきます。

1回のごとの解説は区切りがいい所までで止めますので勉強したい所まで勉強して下さい。

特にLaravelを始めたての人にとって難しいと感じる内容もあるはずです。

難しいと感じたら理解できた所までの学習にした方がいいと思います。


アプリの機能

クイズアプリの全ての解説を読んで実装できる機能は以下になります。

機能が少なそうに見えますが内容盛りだくさんだと思います。

それでは解説します。


プロジェクトの作成とログイン機能

Laralelのプロジェクトを作成してBreezeをインストールして下さい。(ユーザーはまだ追加しないで下さい)

プロジェクト名はquizとします。

トップページが下記になったら成功です。

20241229_112559_quiz1.jpg


権限テーブルの作成

今回のアプリでクイズを作成できるのは管理人だけです。

だからユーザーに権限を持たせないといけないのですがまずは権限のテーブルを作成してデータの投入をします。

権限のテーブルはrole_typesとします。

下記のコマンドを叩きます。

php artisan make:model RoleType -m

「quiz > database > migrations > 本日の日付_create_role_types_table.php」に下記の記述をします。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('role_types', function (Blueprint $table) {
            $table->id();
            $table->string('name');       //この行を追加
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('role_types');
    }
};

記述したら下記のコマンドを叩きます。

php artisan migrate

これでrole_typesテーブルが作成されました。

つぶやきアプリを作った時はテーブルのレコードを作成する時に作成のページで作成していました。

今回はrole_typesテーブルのnameカラムの値として管理人とユーザーしかなく変更しないのでテーブルにデータを直接投入します。

Seederを使えばそれば実現できます。


role_typesテーブルにSeederを使ってデータを投入する

Seederを作成する為に下記のコマンドを叩きます。

php artisan make:seeder RoleTypeSeeder

「RoleTypeSeeder」の「R」は大文字にします。

コマンドを叩くと「quiz > database > seeders > RoleTypeSeeder.php」が作成されます。

下記の記述をします。

<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\RoleType;                   // この行を追加

class RoleTypeSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {


        // ここから追加
        RoleType::insert([
            [
                'name' => '管理人',
                'created_at' => '2024-12-29',
                'updated_at' => '2024-12-29'
            ],
            [
                'name' => 'ユーザー',
                'created_at' => '2024-12-29',
                'updated_at' => '2024-12-29'
            ],
        ]);
        // ここまで追加

        
    }
}

use App\Models\RoleType;」はアクセスするテーブルに対応するモデル名を記述します。

今回アクセスするテーブルはrole_typesテーブルなので対応するモデル名はRoleTypeです。

下記のコードについて説明します。

RoleType::insert([
    [
        'name' => '管理人',
        'created_at' => '2024-12-29',
        'updated_at' => '2024-12-29'
    ],
    [
        'name' => 'ユーザー',
        'created_at' => '2024-12-29',
        'updated_at' => '2024-12-29'
    ],
]);

最初の行の「RoleType」はモデル名です。

「[ ]」のかたまりの中にname・created_at・updated_atがありますがカラム名です。

「[ ]」のかたまりが2つありますが1つ1つがレコードに入るデータと思っていいです。

RoleTypeSeeder.phpを実行する為に「quiz > database > seeders > DatabaseSeeder.php」に記述します。

<?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        // \App\Models\User::factory(10)->create();

        // \App\Models\User::factory()->create([
        //     'name' => 'Test User',
        //     'email' => 'test@example.com',
        // ]);

        $this->call(RoleTypeSeeder::class);          //この行を追加
    }
}

RoleTypeSeeder」は先ほど作成したRoleTypeSeeder.phpのことです。

記述が終わったら下記のコマンドでRoleTypeSeeder.phpをテーブルに反映させます。

php artisan db:seed --class=RoleTypeSeeder

これでrole_typesテーブルにレコードが作成されたはずです。

20241229_155803_quiz2.jpg

それではユーザーに権限を持たせます。


usersテーブルにカラムの追加

ユーザーに権限を持たせるにはusersテーブルにrole_typesテーブルの情報が追加されればいいので追加します。

追加するカラム名はrole_type_idになりますがなぜrole_type_idなのかを説明します。

あるテーブル(今回はusersテーブル)があるテーブル(今回はrole_typesテーブル)の情報を使う時はリレーションというのを使います。

生言語のリレーションと同じです。

Laravelの場合のリレーションはモデルを連携することを指します。

権限(role_types)は管理人とユーザーがありますが例えばユーザーの権限に対して複数の登録ユーザーが紐付きます。

つまり1つの権限に対して複数のユーザーが紐づいていると言えます。

リレーションをする時は親と子があるのですが1人が親と考えて複数いるのが子と考えていいです。

ということは今回だと親が権限と考えて子がユーザーと考えることができます。

子テーブル(users)に親テーブル(role_types)の情報を追加する時は子テーブルに「親テーブル名_id」(sは取る)カラムを追加するルールがLaravelでは決められています。

だからusersテーブルにrole_type_idカラムを追加します。

下記のコマンドを叩きます。

php artisan make:migration add_カラム名_to_table_テーブル名 --table=テーブル名

カラム名はrole_type_idなのでコマンドは下記になります。

php artisan make:migration add_role_type_id_to_table_users --table=users

マイグレーションファイルに下記の記述をします。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->unsignedBigInteger('role_type_id')->after('email');       //この行を追加        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('role_type_id');      //この行を追加
        });
    }
};

「unsignedBigInteger」が初めて登場しますがリレーションを使う時のデータ型はunsingedBigIntegerと決まっています。

「->after('email')」はemailカラムの後ろにrole_type_idカラムを作成するという意味です。

$table->dropColumn('role_type_id');」はマイグレーションファイルの内容を元に戻してテーブルの内容を元に戻す下記のコマンドを叩いた時用です。

php artisan migrate:rollback

$table->dropColumn('role_type_id');」があることでrollbackをした時に追加したrole_type_idカラムを削除します。

テーブルの内容を戻した時にrole_type_idカラムが残っているとテーブルの状態が変になるので追加したカラムは削除しないといけません。

記述が終わったら下記のコマンドを叩いてusersテーブルにrole_type_idカラムを追加します。

php artisan migrate

role_type_idカラムが追加されているのを確認して下さい。

20241229_164430_quiz3.jpg

それではユーザーに権限を持たせます。


ユーザーに権限を持たせる

権限の振り分け方は色々とあると思いますが今回はこうします。

権限は管理人とユーザーですが最初の登録ユーザーの権限を管理人にしてそれ以外の登録ユーザーの権限をユーザーにします。

だからユーザー登録の際にidが1の登録ユーザーだけ管理人の権限(role_type_idが1)にしてそれ以外の登録ユーザーの権限をユーザーの権限(role_type_idが2)にします。

リレーションを理解している人はrole_type_idを1にしたり2にしたりする意味が理解できるはずですがプログラムを初めて学ぶ人にとっては意味が分からないと思うので説明します。

最初がぎこちない感じがすると思いますが慣れれば当たり前になりますので頑張って理解して下さい。

role_typesテーブルのidカラムの値に注目します。

20241229_165910_quiz4.jpg

今レコードのidカラムの値は1と2があります。

id=1がusersテーブルのrole_type_idカラムの値が1の場合と対応してid=2がusersテーブルのrole_type_idカラムの値が2の場合と対応しています。

これはリレーションのルールです。

だから管理人の権限を付けたいならusersテーブルのrole_type_idカラムの値に1を設定してユーザーの権限を設定したいならrole_type_idカラムの値に2を設定しないといけません。

それではユーザー登録にrole_type_idカラムの値を設定する記述をします。

「quiz > App > Http > Controllers > Auth > RegisteredUserController」に追記します。

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules;
use Illuminate\View\View;

class RegisteredUserController extends Controller
{
    /**
     * Display the registration view.
     */
    public function create(): View
    {
        return view('auth.register');
    }

    /**
     * Handle an incoming registration request.
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
            'password' => ['required', 'confirmed', Rules\Password::defaults()],
        ]);


        // ここから追加
        $userCount = User::count();

        if ($userCount == 0) {
            $role_type_id = 1;
        } else {
            $role_type_id = 2;
        }
        // ここまで追加


        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
            'role_type_id' => $role_type_id             //この行を追加
        ]);

        event(new Registered($user));

        Auth::login($user);

        return redirect(RouteServiceProvider::HOME);
    }
}

User::count();」は登録するユーザーの数を数えます。

下記のコードで登録ユーザーがいない場合はrole_type_idカラムの値に1を設定して登録ユーザーがいる場合はrole_type_idカラムの値に2を設定します。

if ($userCount == 0) {
    $role_type_id = 1;
} else {
    $role_type_id = 2;
}

今の状態でユーザー登録をすると下記のエラーが発生します。

SQLSTATE[HY000]: General error: 1364 Field 'role_type_id' doesn't have a default value

なぜか分かりますか?

テーブルにカラムを追加した時は必ずテーブルに対応するモデルに追加したカラムの値の登録を許可する記述をしないといけないと以前解説しています。

role_type_idカラムはusersテーブルのカラムなのでUser.phpに追記します。

protected $fillable = [
    'name',
    'email',
    'password',
    'role_type_id'     //この行を追加
];

ユーザーを複数登録してrole_type_idの値がid=1の場合だけ1になっていることを確認して下さい。

20241229_174334_quiz5.jpg
今回はここまでです。

次回の解説からrole_type_idカラムの値が1の場合だけクイズの問題を作成できるようにします。


戻る