1
4

More than 3 years have passed since last update.

laravel8マルチログイン

Last updated at Posted at 2021-03-07

はじめに

フロント画面と管理画面でログイン認証を分けたい場合の
実装方法を記載する。
業務ではオリジナルテンプレートを使用するパターンが多いので、
『laravel/ui』なし、独自コントローラーでの実装を目指します。
ログイン機能を作成します。
※ログアウトやリマインダーは今回はやりません。

やりたいこと

users:顧客
admins:管理者
別々のログイン画面でログイン認証可能にする。

環境

PHP 7.3.2
Laravel Framework 8.5.12
MariaDB 10.1.38

事前準備

Composerをインストール
https://weblabo.oscasierra.net/php-composer-windows-install/

laravel8環境構築

LaravelをComposerでインストール
composer create-project --prefer-dist laravel/laravel LaravelMultiLogin "8.*"
※しばらく時間がかかります

ディレクトリ移動
cd LaravelMultiLogin
サーバ起動
php artisan serve

ブラウザでhttp://localhost:8000/
にアクセスしてLaravelって表示されれば成功

ライブラリインストール

・fortify
composer require laravel/fortify
・laravelcollective
composer require laravelcollective/html

各種設定

①config/app.php 言語設定変更

config/app.php
'timezone' => 'Asia/Tokyo',
'locale' => 'ja',
'fallback_locale' => 'ja',
'faker_locale' => 'ja_JP',`

キャッシュクリア
php artisan config:cache

②「.env」設定変更(DB接続先の環境に合わせて変更)

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=root
DB_PASSWORD=

③エラーメッセージ日本語化

下記、からダウンロード
https://github.com/Laravel-Lang/lang/tree/master/src/ja

メッセージファイルを配置
C:\XXX\LaravelMultiLogin\resources\lang\ja\auth.php
C:\XXX\LaravelMultiLogin\resources\lang\ja\pagination.php
C:\XXX\LaravelMultiLogin\resources\lang\ja\passwords.php
C:\XXX\LaravelMultiLogin\resources\lang\ja\validation-inline.php
C:\XXX\LaravelMultiLogin\resources\lang\ja\validation.php

validation.php
'attributes' => [
    'email' => 'メールアドレス',
    'password' => 'パスワード'
],

テーブル作成

マイグレーション作成

database\migrations\XXXX_XX_XX_XXXXXX_create_admins_table.php
    public function up()
    {
        Schema::create('admins', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

マイグレーション実行
php artisan migrate

SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter tableusersadd uniqueusers_email_unique(email))

上記エラーが発生した場合は、下記設定をし再度実行
※一度DB内で作成されたテーブルを全て削除

app\Providers\AppServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema; // 追加

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
        Schema::defaultStringLength(191); // 追加
    }
}

ログインデータ作成

seedファイル作成
php artisan make:seed MultiAuthTableSeeder\MultiAuthTableSeeder.php

        \DB::table('users')->insert([
            [
                'name' => 'user',
                'email' => 'user@example.com',
                'email_verified_at' => now(),
                'password' => \Hash::make('password'),
                'created_at' => now(),
                'updated_at' => now()
            ],[
                'name' => 'user2',
                'email' => 'user2@example.com',
                'email_verified_at' => now(),
                'password' => \Hash::make('password'),
                'created_at' => now(),
                'updated_at' => now()
            ]
        ]);
        \DB::table('admins')->insert([
            [
                'name' => 'admin',
                'email' => 'admin@example.com',
                'email_verified_at' => now(),
                'password' => \Hash::make('123456789'),
                'created_at' => now(),
                'updated_at' => now()
            ],[
                'name' => 'admin2',
                'email' => 'admin2@example.com',
                'email_verified_at' => now(),
                'password' => \Hash::make('123456789'),
                'created_at' => now(),
                'updated_at' => now()
            ]
        ]);
database\seeders\DatabaseSeeder.php
    public function run()
    {
        // \App\Models\User::factory(10)->create();
        $this->call(MultiAuthTableSeeder::class); // 追加
    }

seed実行
php artisan migrate:fresh --seed

コンフィグファイルを変更

config/auth.php
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'admins' => [               // 追加
            'driver' => 'session',  // 追加
            'provider' => 'admins', // 追加
        ],                          // 追加

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
        'admins' => [                               // 追加
            'driver' => 'eloquent',                 // 追加
            'model' => App\Models\Admin::class,    // 追加
        ],                                        // 追加
    ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
        'admins' => [                       // 追加
            'provider' => 'admins',         // 追加
            'table' => 'password_resets',   // 追加
            'expire' => 60,                 // 追加
            'throttle' => 60,               // 追加
        ],
    ],

キャッシュクリア
php artisan config:cache

モデル作成

php artisan make:model Admin -m
※Userモデルはあるため不要

app/Models/Admin.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 Authenticatable // 変更
{
    use HasFactory;
}
routes/web.php
// ユーザーログイン
Route::get('user_login', [\App\Http\Controllers\UserLoginController::class, 'showLoginForm'])->name('user_login');
Route::post('user_login', [\App\Http\Controllers\UserLoginController::class, 'login']);

Route::prefix('user')->group(function () {

    Route::middleware('auth:web')->group(function () {
        Route::get('dashboard', function () {
            Auth::guard('web')->logout();
            return 'ユーザーでログイン';
        });
    });
});

Route::prefix('admin')->group(function () {
    // 管理者ログイン
    Route::get('admin_login', [\App\Http\Controllers\AdminLoginController::class, 'showLoginForm'])->name('admin.admin_login');
    Route::post('admin_login', [\App\Http\Controllers\AdminLoginController::class, 'login']);


    Route::middleware('auth:admins')->group(function () {
        Route::get('dashboard', function () {
            Auth::guard('admins')->logout();
            return '管理者でログイン';
        });
    });
});

コントローラー作成

php artisan make:controller UserLoginController

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

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserLoginController extends Controller
{
    //
    public function showLoginForm()
    {
        return view('user.login');
    }

    public function login(Request $request)
    {
        $this->validate($request, [
            'email' => 'required|email', 'password' => 'required',
        ]);

        $credentials = $request->only(['email', 'password']);

        if (\Auth::guard('web')->attempt($credentials)) {

            return redirect('user/dashboard'); // ログインしたらリダイレクト

        }

        return back()->withInput($request->only('email'))
            ->withErrors([
                'email' => ['認証情報が記録と一致しません。']
            ]);
    }
}

view作成

未ログイン時のリダイレクト先変更

/app/Exceptions/Handler.php
use Illuminate\Auth\AuthenticationException; // 追加

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['message' => $exception->getMessage()], 401);
        }
        if ($request->is('admin') || $request->is('admin/*')) {
            return redirect('admin/admin_login');
        }
        return redirect('user_login');
    }

unauthenticated メソッド追加

resources/views/user/login.blade.php
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>ログイン</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" crossorigin="anonymous">
</head>
<body>
<div id="app">
    <div class="container">
        <div class="row justify-content-center mt-5">
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">ユーザーログイン</div>
                    <div class="card-body">
                        {{ Form::open(['method' => 'post']) }}
                            <div class="form-group">
                                {{ Form::label('email', 'メールアドレス') }}
                                {{ Form::text('email', null, [
                                    'class' => 'form-control' . ($errors->has('email') ? ' is-invalid' : '')
                                ]) }}
                                @error('email')
                                    <div class="invalid-feedback">
                                        {{ $message }}
                                    </div>
                                @enderror
                            </div>
                            <div class="form-group">
                                {{ Form::label('password', 'パスワード') }}
                                {{ Form::password('password', [
                                    'class' => 'form-control' . ($errors->has('password') ? ' is-invalid' : '')
                                ]) }}
                                @error('password')
                                    <div class="invalid-feedback">
                                        {{ $message }}
                                    </div>
                                @enderror
                            </div>
                            <div>
                                <button type="submit" class="btn btn-primary">ログイン</button>
                            </div>
                        {{ Form::close() }}
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

php artisan make:controller AdminLoginController

app/Http/Controllers/AdminLoginController.php

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class AdminLoginController extends Controller
{
    //
    public function showLoginForm()
    {
        return view('admin.login');
    }

    public function login(Request $request)
    {
        $this->validate($request, [
            'email' => 'required|email', 'password' => 'required',
        ]);

        $credentials = $request->only(['email', 'password']);

        if (\Auth::guard('admins')->attempt($credentials)) {

            return redirect('admin/dashboard'); // ログインしたらリダイレクト

        }

        return back()->withInput($request->only('email'))
            ->withErrors([
                'email' => ['認証情報が記録と一致しません。']
            ]);
    }
}
resources/views/admin/login.blade.php
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>ログイン</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" crossorigin="anonymous">
</head>
<body>
<div id="app">
    <div class="container">
        <div class="row justify-content-center mt-5">
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">管理者ログイン</div>
                    <div class="card-body">
                        {{ Form::open(['method' => 'post']) }}
                            <div class="form-group">
                                {{ Form::label('email', 'メールアドレス') }}
                                {{ Form::text('email', null, [
                                    'class' => 'form-control' . ($errors->has('email') ? ' is-invalid' : '')
                                ]) }}
                                @error('email')
                                    <div class="invalid-feedback">
                                        {{ $message }}
                                    </div>
                                @enderror
                            </div>
                            <div class="form-group">
                                {{ Form::label('password', 'パスワード') }}
                                {{ Form::password('password', [
                                    'class' => 'form-control' . ($errors->has('password') ? ' is-invalid' : '')
                                ]) }}
                                @error('password')
                                    <div class="invalid-feedback">
                                        {{ $message }}
                                    </div>
                                @enderror
                            </div>
                            <div>
                                <button type="submit" class="btn btn-primary">ログイン</button>
                            </div>
                        {{ Form::close() }}
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

参考記事

https://blog.capilano-fw.com/?p=8159
https://www.webopixel.net/php/1665.html

1
4
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
1
4