Laravel 10 入門トップページ


目次

  1. 全体の概要
  2. Laravel によるユーザ認証
    1. 概要
    2. プロジェクトの作成と初期設定
    3. メールの設定
    4. Laravel Breeze のインストール
    5. ユーザ登録機能の動作確認
    6. シーダによるテストユーザの登録
    7. テーブルにログイン ID の属性を追加
    8. ユーザ登録機能の修正
    9. ログイン ID でログインするように変更
    10. メールアドレスの検証
    11. シーダの修正
    12. 検証メールの有効期限と再送信
    13. セッション継続時間の確認と変更
    14. メールアドレスの変更
    15. パスワードの変更
    16. アカウントの削除
  3. ユーザ認証を備えたコメント掲示板の開発
  4. マルチ認証の実現

Laravel でユーザ認証とマルチ認証を実現する

Laravel によるユーザ認証

ユーザ登録機能の修正

ユーザのテーブルにログイン ID と学籍番号の列(属性)を追加したので,ユーザ登録時にこれらの情報が登録できるように修正していきます.

まずモデルのファイルで $fillable 属性にこれらを追加して,ユーザ自身がログイン ID と学籍番号を設定(変更)できるようにします.

app/Models/User.php
<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'student_id',
        'login_id',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];
}

次はログイン画面のビューです.現在のファイルの状態は次のとおりです.

resources/views/auth/register.blade.php
<x-guest-layout>
    <form method="POST" action="{{ route('register') }}">
        @csrf

        <!-- Name -->
        <div>
            <x-input-label for="name" :value="__('Name')" />
            <x-text-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" />
            <x-input-error :messages="$errors->get('name')" class="mt-2" />
        </div>

        <!-- Email Address -->
        <div class="mt-4">
            <x-input-label for="email" :value="__('Email')" />
            <x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autocomplete="username" />
            <x-input-error :messages="$errors->get('email')" class="mt-2" />
        </div>

        <!-- Password -->
        <div class="mt-4">
            <x-input-label for="password" :value="__('Password')" />

            <x-text-input id="password" class="block mt-1 w-full"
                            type="password"
                            name="password"
                            required autocomplete="new-password" />

            <x-input-error :messages="$errors->get('password')" class="mt-2" />
        </div>

        <!-- Confirm Password -->
        <div class="mt-4">
            <x-input-label for="password_confirmation" :value="__('Confirm Password')" />

            <x-text-input id="password_confirmation" class="block mt-1 w-full"
                            type="password"
                            name="password_confirmation" required autocomplete="new-password" />

            <x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
        </div>

        <div class="flex items-center justify-end mt-4">
            <a class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" href="{{ route('login') }}">
                {{ __('Already registered?') }}
            </a>

            <x-primary-button class="ml-4">
                {{ __('Register') }}
            </x-primary-button>
        </div>
    </form>
</x-guest-layout>

これを次のとおり変更し(付け加え)ます.

resources/views/auth/register.blade.php
<x-guest-layout>
    <form method="POST" action="{{ route('register') }}">
        @csrf

        <!-- Name -->
        <div>
            <x-input-label for="name" :value="__('Name')" />
            <x-text-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" />
            <x-input-error :messages="$errors->get('name')" class="mt-2" />
        </div>

        <!-- Student ID -->
        <div class="mt-4">
            <x-input-label for="student_id" :value="__('Student ID')" />
            <x-text-input id="student_id" class="block mt-1 w-full" type="text" name="student_id" :value="old('student_id')" required autocomplete="student_id" />
            <x-input-error :messages="$errors->get('student_id')" class="mt-2" />
        </div>

        <!-- Login ID -->
        <div class="mt-4">
            <x-input-label for="login_id" :value="__('Login ID')" />
            <x-text-input id="login_id" class="block mt-1 w-full" type="text" name="login_id" :value="old('login_id')" required autocomplete="login_id" />
            <x-input-error :messages="$errors->get('login_id')" class="mt-2" />
        </div>

        <!-- Email Address -->
        <div class="mt-4">
            <x-input-label for="email" :value="__('Email')" />
            <x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autocomplete="username" />
            <x-input-error :messages="$errors->get('email')" class="mt-2" />
        </div>

        <!-- Password -->
        <div class="mt-4">
            <x-input-label for="password" :value="__('Password')" />

            <x-text-input id="password" class="block mt-1 w-full"
                            type="password"
                            name="password"
                            required autocomplete="new-password" />

            <x-input-error :messages="$errors->get('password')" class="mt-2" />
        </div>

        <!-- Confirm Password -->
        <div class="mt-4">
            <x-input-label for="password_confirmation" :value="__('Confirm Password')" />

            <x-text-input id="password_confirmation" class="block mt-1 w-full"
                            type="password"
                            name="password_confirmation" required autocomplete="new-password" />

            <x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
        </div>

        <div class="flex items-center justify-end mt-4">
            <a class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" href="{{ route('login') }}">
                {{ __('Already registered?') }}
            </a>

            <x-primary-button class="ml-4">
                {{ __('Register') }}
            </x-primary-button>
        </div>
    </form>
</x-guest-layout>

コントローラを修正して,ユーザ登録時にログイン ID と学籍番号もテーブルに保存するようにします.

app/Http/Controllers/Auth/RegisteredUserController.php
<?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'],
            'student_id' => ['required', 'integer', 'min:6100000', 'max:6399999', 'unique:'.User::class],
            'login_id' => ['required', 'string', 'min:1', 'max:255', 'unique:'.User::class],
            'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
            'password' => ['required', 'confirmed', Rules\Password::defaults()],
        ]);

        $user = User::create([
            'name' => $request->name,
            'student_id' => $request->student_id,
            'login_id' => $request->login_id,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        event(new Registered($user));

        Auth::login($user);

        return redirect(RouteServiceProvider::HOME);
    }
}

Web サーバを起動してユーザ登録ページにアクセスします.Student ID と Login ID の入力ボックスが追加されました.

laravel10-2023-auth-12.png

適当な値を入力して「REGISTER」を押下します.

laravel10-2023-auth-13.png

ユーザ登録が完了してそのままダッシュボードページが表示されました.最後にログアウトすると良いでしょう.

laravel10-2023-auth-15.png

今のユーザ登録の作業前後でデータベースの内容を確認します.

sqlite> select * from users; ⏎ # ユーザ登録前
id|name|email|email_verified_at|password|remember_token|created_at|updated_at|login_id|student_id
1|A. Sample|a@sample.com||$2y$12$xKLWZJSJqxcu8bLNA/o2X.CvZlDWsi0t3tIVVzcFS7RzELoVQWhzC||2023-11-03 00:01:01|2023-11-03 00:01:01|user_a|6300997
2|B. Sample|b@sample.com||$2y$12$RjXhibG00aYYv8pvZ2.5MOHvdsvDlfxtdWdyoz3zUx0074MHLbBQS||2023-11-03 00:02:01|2023-11-03 00:02:01|user_b|6300998
3|C. Sample|c@sample.com||$2y$12$LGBYC5Pi5eezXPbSLVAutuNWpd8u7M/T4lVaUC3vGpp6qqF3Y65Hi||2023-11-03 00:03:01|2023-11-03 00:03:01|user_c|6300999
sqlite> select * from users; ⏎ # ユーザ登録後
id|name|email|email_verified_at|password|remember_token|created_at|updated_at|login_id|student_id
1|A. Sample|a@sample.com||$2y$12$xKLWZJSJqxcu8bLNA/o2X.CvZlDWsi0t3tIVVzcFS7RzELoVQWhzC||2023-11-03 00:01:01|2023-11-03 00:01:01|user_a|6300997
2|B. Sample|b@sample.com||$2y$12$RjXhibG00aYYv8pvZ2.5MOHvdsvDlfxtdWdyoz3zUx0074MHLbBQS||2023-11-03 00:02:01|2023-11-03 00:02:01|user_b|6300998
3|C. Sample|c@sample.com||$2y$12$LGBYC5Pi5eezXPbSLVAutuNWpd8u7M/T4lVaUC3vGpp6qqF3Y65Hi||2023-11-03 00:03:01|2023-11-03 00:03:01|user_c|6300999
4|学院太郎|taro@sample.com||$2y$12$bNCT.ww3ZiXZmZSxlvD0NuBzG5OpzK4PnxVSEUbe3i.jgndsoY2Tu||2023-11-03 10:51:17|2023-11-03 10:51:17|taro|6398901
sqlite>

目次に戻る