【Laravel 認証機能】Adminユーザの作成 4. 管理者ログイン機能 & 管理者ページの作成

Laravel 認証機能 – 管理者ログイン機能 & 管理者ページの作成

ここからは、これまで準備してきたデータベース設定、ガード&ミドルウェアの仕組みを利用して、ログイン機能の管理者用ユーザ対応と、管理者ユーザ専用ページを実装していきます。

これまでの内容
【Laravel11 認証機能】Adminユーザの作成 1. データベース管理設定
【Laravel11 認証機能】Adminユーザの作成 2. ガード・プロバイダ設定 &ミドルウェア作成

環境: Laravel 11, PHP 8.3.14

要件・仕様

本記事で実装する管理者用機能の要件及び、仕様は以下です。

認証

    • 管理者ユーザのログインには、通常ユーザと共通のログイン画面(/login)を使用します。
    • ログイン処理では、管理者ユーザを優先して認証し、認証に成功した場合は管理者専用ページ(/admin)へ遷移させます。
    • 管理者ユーザと通常ユーザのいずれか一方のみがログイン可能とし、同一ブラウザでの同時ログインを禁止します。

アクセス制御

  • 管理者ユーザがログイン中に以下の挙動を実現します:
    • TOPページ/):
      • 通常ユーザ向けのダッシュボードリンクの代わりに、管理者専用ページ(/admin)へのリンクを表示します。
    • ダッシュボードページ/dashboard)へのアクセス:
      • 管理者ユーザが通常ユーザ用のダッシュボードページのURLにアクセスした場合、トップページ(/)にリダイレクトします。
    • ログイン画面/login)へのアクセス:
      • ログイン中のユーザは通常ユーザと同様、トップページ(/)にリダイレクトします。
    • プロフィールページ/profile):
      • 通常ユーザ、管理者ユーザどちらかでログイン中のみプロフィールページ(/profile)を閲覧可能です。

視覚的な区別

  • 管理者ユーザログイン時には、画面に通常ユーザとは異なる背景色やスタイルを適用し、視覚的に管理者用ページであることを明確にします。

実装

ログイン用コントローラの変更

ログイン用のコントローラクラスのログイン処理に管理者用のログイン認証を追加します。
app/Http/Controllers/Auth/LoginController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    /**
     * ログインフォームを表示する
     *
     * @return \Illuminate\View\View
     */
    public function showLoginForm()
    {
        return view('auth.login');
    }

    /**
     * ユーザーのログイン処理を実行する
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function login(Request $request)
    {
        // 1. リクエストのデータを検証する
        $credentials = $request->validate([
            'email' => ['required', 'email'],
            'password' => ['required'],
        ]);

        // 2. 管理者ユーザーとしての認証を試みる
        if (Auth::guard('admin')->attempt($credentials, $request->filled('remember'))) {
            $request->session()->regenerate();
            // 認証成功: 管理者ページにリダイレクト
            return redirect()->intended(route('admin.index'));
        }

        // 3. 一般ユーザーとしての認証を試みる
        if (Auth::attempt($credentials, $request->filled('remember'))) {
            // 認証成功: 一般ダッシュボードにリダイレクト
            $request->session()->regenerate();
            return redirect()->intended('dashboard');
        }

        // 4. 認証に失敗した場合
        return back()->withErrors([
            'email' => 'ログイン情報が正しくありません。',
        ])->onlyInput('email');
    }
}

ページレイアウトの変更

前ページ共通のレイアウト用ビューファイルを修正し、管理者用ユーザログイン時のみ特別なスタイルが適用されるようにします。
resources/views/layouts/app.blade.php

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@yield('title', 'Laravel App')</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: #f8f9fa;
        }
        body.admin {
            background-color: #f0f7ff;
        }
        .container {
            max-width: 500px;
            padding: 20px;
            background-color: #ffffff;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        .admin .container {
            background-color: #ffffff;
            box-shadow: 0 0 15px rgba(13, 110, 253, 0.2);
        }
        .form-label {
            font-weight: bold;
        }
    </style>
</head>
<body class="{{ Auth::guard('admin')->check() ? 'admin' : '' }}">
    <div class="container">
        @yield('content')
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

トップページの変更

トップページ内に管理者用ガードの認証状態をチェックする条件分岐を加えます。

管理者用ユーザでログインしていればユーザ名と、管理者用ページへのリンクを表示します。

resources/views/index.blade.php

@extends('layouts.app')

@section('title', 'トップページ')

@section('content')
    <h2 class="text-center mb-4">トップページ</h2>
    @if(Auth::guard('admin')->check())
        <p class="text-center">管理者としてログイン中: {{ Auth::guard('admin')->user()->name }}</p>
        <div class="d-flex justify-content-center">
            <a href="{{ route('admin.index') }}" class="btn btn-primary mx-2">管理者ページ</a>
        </div>
    @elseif(Auth::check())
        <p class="text-center">ログイン中: {{ Auth::user()->name }}</p>
        <div class="d-flex justify-content-center">
            <a href="{{ route('dashboard') }}" class="btn btn-primary mx-2">ダッシュボード</a>
        </div>
    @else
        <div class="d-flex justify-content-center">
            <a href="{{ route('register') }}" class="btn btn-outline-primary mx-2">ユーザー登録</a>
            <a href="{{ route('login') }}" class="btn btn-outline-primary mx-2">ログイン</a>
        </div>
    @endif
@endsection

管理者用ページ作成

管理者専用ページのテンプレートを作成します。

resources/views/admin/index.blade.php

@extends('layouts.app')

@section('title', '管理者専用ページ')

@section('content')
    <h2 class="text-center mb-4">管理者専用ページ</h2>
    <div class="d-flex justify-content-center">
        <a href="{{ route('home') }}" class="btn btn-outline-secondary mx-2">トップページに戻る</a>
    </div>
    <form class="text-center mt-4" action="{{ route('logout') }}" method="POST" class="d-inline">
        @csrf
        <button type="submit" class="btn btn-danger mx-2">ログアウト</button>
    </form>
@endsection

認証済み共通ページ: プロフィール

通常ユーザ、管理者用ページ共通でログイン時に閲覧できるプロフィールページを作成します。
resources/views/profile.blade.php


@extends('layouts.app')

@section('title', 'プロフィール')

@section('content')
    <h2 class="text-center mb-4">プロフィール</h2>
    @if (Auth::guard('admin')->check() || Auth::check())
        <p class="text-center">ユーザ名: {{ Auth::guard('admin')->user()->name ?? Auth::user()->name }}</p>
        <p class="text-center">メールアドレス: {{ Auth::guard('admin')->user()->email ?? Auth::user()->email }}</p>
    @endif
@endsection

ルーティングの作成・変更

ルーティングファイルに管理者用ページのURLと新しく追加したミドルウェアの設定を行います。

routes/web.php


<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\Auth\RegisterController;
use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\Auth\LogoutController;

// トップページのルート
Route::get('/', [HomeController::class, 'index'])->name('home');

// ダッシュボードのルート(通常ユーザでのログインが必要)
Route::get('/dashboard', [HomeController::class, 'dashboard'])
    ->middleware('auth')
    ->name('dashboard');

// ユーザー登録のルート
Route::get('register', [RegisterController::class, 'showRegistrationForm'])
    ->name('register')
    ->middleware('custom.guest');
Route::post('register', [RegisterController::class, 'register']);

// ログインのルート
Route::get('login', [LoginController::class, 'showLoginForm'])
    ->middleware('custom.guest')
    ->name('login');
Route::post('login', [LoginController::class, 'login']);

// ログアウトのルート
Route::post('logout', [LogoutController::class, 'logout'])
    ->name('logout');

// 管理者用のルート
Route::prefix('admin')->group(function () {
    Route::get('/', function () {
        return view('admin.index');
    })
    ->name('admin.index')
    ->middleware('admin');
});

// プロフィール(ログイン中のみ閲覧可)
Route::middleware('authenticated')->group(function () {
    Route::get('profile', function () {
        return view('profile');
    });
});

ログイン画面(/login)へのミドルウェアをcustom.guestに変更。

管理者用ページへのリクエストはadminミドルウェアでadminガードの認証で保護します。
(現在は管理者ページのみですが、Route::prefixでグルーピングしています)

新たに作成したプロフィールページ(/profille)はミドルウェアauthenticatedにて、デフォルト & adminの両ガード共通で保護します。

まとめ

複数回に渡り、Laravel11の認証機能に自作で管理者ユーザ機能を追加する方法を解説してきました。

今回の仕様では管理者ページ自体に特別な内容を含みませんでしたが、今後作成するアプリケーションの要件に応じて、ここまで作成してきた認証やアクセス制限の仕組みを土台にして、機能追加等カスタマイズを行なうことが出来ますので、是非参考にしてみてください。

Follow me!