0
0

Laravel11でマルチログイン機能を実装してみた

Posted at

はじめに

この記事は、Laravel11でマルチログイン機能を実装する方法について書いています。ぱぱっと実装したい方向けに、細かい説明は省いています。

実装内容について詳しく知りたい場合は、以下を参考にしていただくと、より理解が深まると思います。

前提

Laravel11の環境構築が完了している方を対象としています。

マルチログインの実装

新たにadminsテーブルを作成して、管理者用のログイン機能を実装します。

下記の順に作業を進めていきます。

  1. 管理者テーブルとモデルを作成
  2. ガード・プロバイダを設定
  3. コントローラーを作成
  4. ルーティングを設定
  5. Bladeファイルを作成
  6. ログイン状態、未ログイン状態の場合のリダイレクト先を設定

管理者テーブルとモデルを作成

次のコマンドを実行して、マイグレーションファイルとモデルファイルを作成します。

php artisan make:model -m Admin

マイグレーションファイルを修正します。

<?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('admins', function (Blueprint $table) {
            $table->id();
+            $table->string('email')->unique();
+            $table->string('password');
            $table->timestamps();
        });
    }

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

マイグレーションを実行します。

php artisan migrate

モデルファイルを修正します。

app/Models/Admin.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
-use Illuminate\Database\Eloquent\Model;
+use Illuminate\Foundation\Auth\User as Authenticatable;

-class Admin extends Model
+class Admin extends Authenticatable
{
    use HasFactory;
+    
+    protected $fillable = [
+        'email',
+        'password',
+    ];
}

ガード・プロバイダを設定

管理者用のガードとプロバイダを追加します。
コメント部分は省略しています。

config/auth.php
<?php
return [
    'defaults' => [
        'guard' => env('AUTH_GUARD', 'web'),
        'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
    ],

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
+        'admin' => [
+            'driver' => 'session',
+            'provider' => 'admins',
+        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => env('AUTH_MODEL', App\Models\User::class),
        ],
+       'admins' => [
+            'driver' => 'eloquent',
+            'model' => App\Models\Admin::class,
+        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
            'expire' => 60,
            'throttle' => 60,
        ],
    ],

    // 略

    'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),

];

コントローラーを作成

コントローラーを作成します。

php artisan make:controller AdminLoginController

作成したファイルを修正します。

app/Http/Controllers/AdminLoginController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;

class AdminLoginController extends Controller
{
-   //
+   public function create()
+   {
+        return view('admin.login');
+    }
+
+    public function store(Request $request)
+    {
+        $credentials = $request->validate([
+            'email' => ['required', 'email'],
+            'password' => ['required'],
+        ]);
+
+        if (Auth::guard('admin')->attempt($credentials)) {
+            $request->session()->regenerate();
+
+            return redirect()->intended('/admin/top')->with([
+                'message' => 'ログインしました'
+           ]);
+        }
+
+        return back()->withErrors([
+            'message' => 'メールアドレスかパスワードが間違っています',
+        ])->onlyInput('email');
+    }
+
+    public function destroy(Request $request)
+    {
+        Auth::guard('admin')->logout();
+
+        $request->session()->invalidate();
+
+        $request->session()->regenerateToken();
+
+        return to_route('admin.login');
+    }
}

ルーティングを設定

各機能のルーティングを設定します。

routes/web.php
<?php

use Illuminate\Support\Facades\Route;
+use App\Http\Controllers\AdminLoginController;

Route::get('/', function () {
    return view('welcome');
});

+Route::prefix('admin')->name('admin.')->group(function () {
+    Route::middleware('guest:admin')->group(function() {
+        Route::get('/login', [AdminLoginController::class, 'create'])->name('login');
+        Route::post('/login', [AdminLoginController::class, 'store']);
+    });
+   Route::middleware('auth:admin')->group(function() {
+        Route::get('/top', function() {
+            return view('/admin/top');
+        })->name('top');
+    });
+});

Bladeファイルを作成

トップ画面とログイン画面のBladeファイルを作成します。ログイン後はトップ画面にリダイレクトさせます。

php artisan make:view admin/top
php artisan make:view admin/login

トップ画面のBladeファイルを修正します。

views/admin/top.blade.php
-<div>
-    <!-- Walk as if you are kissing the Earth with your feet. - Thich Nhat Hanh -->
-</div>
+<head>
+    <style>
+        dialog {
+            border: none;
+            outline: none;
+            border-radius: 10px;
+            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
+            padding: 5px 20px;
+            font-family: Arial, sans-serif;
+        }
+    </style>
+</head>
+<div>
+    @session('message')
+        <dialog id="dialog">
+            <p>{{ session('message') }}</p>
+        </dialog>
+    @endsession
+    <h1>トップ画面</h1>
+</div>
+<script>
+    const dialog = document.getElementById('dialog');
+    dialog.show();
+
+    setTimeout(() => {
+        dialog.close();
+    }, 3000);
+</script>

login画面のBladeファイルを修正します。

views/admin/login.blade.php
-<div>
-    <!-- You must be the change you wish to see in the world. - Mahatma Gandhi -->
-</div>
+<div>
+     <form method="POST" action="/admin/login">
+        @csrf
+        @error('message')
+            <div class="alert alert-danger">{{ $message }}</div>
+        @enderror
+        <div>
+            <label for="email">メールアドレス</label>
+            <input type="text" name="email" id="email" required />
+            @error('email')
+                <div class="alert alert-danger">{{ $message }}</div>
+            @enderror
+        </div>
+        <div>
+            <label for="password">パスワード</label>
+            <input type="text" name="password" id="password" required />
+            @error('password')
+                <div class="alert alert-danger">{{ $message }}</div>
+            @enderror
+        </div>
+        <div>
+            <button type="submit">ログイン</button>
+        </div>
+    </form>
+</div>

ログイン状態、非ログイン状態でのリダイレクト先を設定

最後に、リダイレクトの設定をします。

bootstrap/app.php
<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
+use Illuminate\Http\Request;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
-        //
+        // 非ログインユーザー用のリダイレクト設定
+        $middleware->redirectGuestsTo(function (Request $request) {
+            if (request()->routeIs('admin.*')) {
+                return $request->expectsJson() ? null : route('admin.login');
+            }
+        });
+
+        // ログインユーザー用のリダイレクト設定
+        $middleware->redirectUsersTo(function () {
+            if(Auth::guard('admin')) {
+                return route('admin.top');
+            }
+        });
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

以上で実装は完了です。
adminsテーブルに適当なデータを挿入してから、動作確認をしてみてください。

参考

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