Laravel8ではJetStream機能が追加され認証機能を利用するためにはInertia.jsかLivewireを選択してインストールを行う必要があります。Laravel7までlaravel/uiパッケージをインストールして利用していた人にとってはなぜJetSrteamを使わなければならないのかと不満もあったと思います。Laravel8がリリースされてから暫くするとそのような声に答えてか新たにLaravel Breezeパッケージが登場しLivewire, Inertiaを使うことなく簡単に認証機能が実装できるようになりました。またCSSにはtailwindcssが利用されています。

JetStreamは多機能でInertis.jsやLivewireのことを考えないといけないのでLaravelの入門者にとってはハードルが高かったのですが、このパッケージのおかげでこれまでのLaravel7のlaravel/uiのようにシンプルな方法で認証機能を利用することができます。laravel/uiのようにJavaScriptのフレームワークVue.js、Reactを一緒にインストールされないのでなぜという疑問もありますがAlpine.jsという軽量のフレームワークがインストールされるのでモーダルやドロップダウンメニューといった機能であれば比較的容易に実装することが可能です。

簡易的に認証機能を実装することができますが完全に使いこなすためにはJavaScriptフレームワークのAlpine.jsとCSSフレームワークのTailwindcssを新たに学習する必要があります。

Laravel8の日々更新が行われており登場した当時はBreeze+Inertia.js+Vue/Reactという組み合わせはありませんでしたが最新版のLaravel8ではBreeze+Inertia.js+Vue/Reactという組み合わせでもインストールすることができます。

Laravelプロジェクトの作成

動作確認の環境を構築するためにLaravelプロジェクトの作成を行います。laravelコマンドが実行できる環境を前提にしておりnode、npmがインストールされている必要があります。

インストールはlaravelコマンドを利用して実行しますが、composer コマンドでも可能です。laravel_breezeというプロジェクト名をつけていますが名前は任意なので好きな名前をつけて実行してください。


 % laravel new laravel_breeze

 % composer create-project --prefer-dist laravel/laravel laravel_breeze

Laravel Breezeパッケージのインストール

Laravelインストール完了後、Laravel/Breezeパッケージのインストールを行います。


 % cd laravel_breeze
 % composer require laravel/breeze

パッケージのインストールが完了したら、php artisan breeze:installコマンドを実行してください。Laravel Breezeに関連するviewファイルやルートの追加、コントローラーファイルなどが作成されます。


 % php artisan breeze:install
Breeze scaffolding installed successfully.
Please execute the "npm install && npm run dev" command to build your assets.

実行するとnpm install && npm run devを実行するようにメッセージが表示されるのでnpmコマンドを実行してください。


 % npm install && npm run dev

以上で設定は完了です。php artisan serveコマンドで開発サーバを起動すると右上にregisterとloginのリンクが表示されます。


 % php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
Breezeパッケージをインストールし設定を行わないと下記の画像のように画面右上に認証機能(Login, Register)へのリンクは表示されません。
Laravel初期画面右上にリンク
Laravel初期画面右上にリンク

Loginのリンクをクリックすると下記のログイン画面が表示されます。

ユーザログイン画面
ユーザログイン画面

右上のRegisterリンクをクリックするとユーザの登録画面が表示されます。

ユーザ登録画面
ユーザ登録画面

Breezeのインストール直後でもユーザ登録画面でユーザ情報の入力を行うことができるため試しに行ってみるとSQLSTATE[HY000] [2002] Connection refused (SQL: select count(*) as aggregate from `users` where `email` = test@test.comのエラーが発生します。原因はデータベースとの接続設定が行われていないためです。ユーザを登録するにはデータベースの作成と接続設定が必須となります。

データベースの設定(SQLite)

動作確認なので簡易的に利用できるSQLiteデータベースを作成します。SQLite用のデータベースファイルを作成します。


 % touch database/database.sqlite
データベースの設定ファイルであるconfig/database.phpにsqliteで利用するデータベースがdatabase.sqliteであることが記述されていることからdatabaseフォルダにdatabase.sqliteという名前のファイルを作成しています。

.envファイルを開いてDB_CONNECTIONという環境変数をデフォルトのmysqlからsqliteに変更してください。DB_で始まるその他の変数は削除してください。


DB_CONNECTION=sqlite
DB_HOST=127.0.0.1 //削除
DB_PORT=3306 //削除
DB_DATABASE=laravel_breeze //削除
DB_USERNAME=root //削除
DB_PASSWORD= //削除

これでSQLiteデータベースの設定は完了です。テーブルを作成するためphp artisan migrateコマンドを実行してください。下記のようにメッセージが表示されたら正常にテーブルの作成は行われています。


 % php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (4.19ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (1.64ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (1.91ms)

再度registerにアクセスしてユーザの登録を行ってみてください。ユーザの登録が行われるとそのまま/dashboardにリダイレクトされるので下記の画面が表示されます。

ダッシュボード画面
ダッシュボード画面

これだけでLaravelの認証機能を実装することができました。右上にある登録したユーザ名をクリックしてください。ドロップダウンメニューが表示されます。これはAlpine.jsによって実装されています。

Breezeによる認証機能はここまでの処理で利用することができるようになりました。BreezeをインストールすることでLaravelにどのようなことが追加されたのか下記で説明を行っていきます。

認証の設定を理解

関連するファイルの確認

Breezeの認証機能でどのようなファイルが追加されたかはcompserコマンドでlaravel/breezeインストールした後に作成されるvendor¥laravel¥breeze¥src¥Consoleの下にあるInstallCommand.phpファイルを見ると確認することができます。

InstallCommand.phpファイルのhandleメソッドを確認してみましょう。Breezeではtailwindcssとalpine.jsの学習が必要になると冒頭で説明しましたがupdateNodePackagesメソッドでpackage.jsonファイル(インストールするJavaScriptライブラリが記述されているファイル。PHPでいうとcomposer.jsonファイル)にtailwindcssとalpinejsのライブラリ情報が追加されていることがわかります。CSSに関連してpostCSSとそのプラグインであるautoprefixerとpostcss-importもインストールされます。それ以下のコードではFileSystemクラスのensureDirectoryExistsメソッドで指定したフォルダが存在するかチェックし、存在しない場合は作成、作成後はcopyDirectoryであらかじめstubsフォルダに保存されている情報をコピーしています。


public function handle()
{
    if ($this->option('inertia')) {
        return $this->installInertiaStack();
    }

    // NPM Packages...
    $this->updateNodePackages(function ($packages) {
        return [
            '@tailwindcss/forms' => '^0.2.1',
            'alpinejs' => '^2.7.3',
            'autoprefixer' => '^10.1.0',
            'postcss' => '^8.2.1',
            'postcss-import' => '^12.0.1',
            'tailwindcss' => '^2.0.2',
        ] + $packages;
    });

    // Controllers...
    (new Filesystem)->ensureDirectoryExists(app_path('Http/Controllers/Auth'));
    (new Filesystem)->copyDirectory(__DIR__.'/../../stubs/default/App/Http/Controllers/Auth', app_path('Http/Controllers/Auth'));

    // Requests...
    (new Filesystem)->ensureDirectoryExists(app_path('Http/Requests/Auth'));
    (new Filesystem)->copyDirectory(__DIR__.'/../../stubs/default/App/Http/Requests/Auth', app_path('Http/Requests/Auth'));

    // Views...
    (new Filesystem)->ensureDirectoryExists(resource_path('views/auth'));
    (new Filesystem)->ensureDirectoryExists(resource_path('views/layouts'));
    (new Filesystem)->ensureDirectoryExists(resource_path('views/components'));

    (new Filesystem)->copyDirectory(__DIR__.'/../../stubs/default/resources/views/auth', resource_path('views/auth'));
    (new Filesystem)->copyDirectory(__DIR__.'/../../stubs/default/resources/views/layouts', resource_path('views/layouts'));
    (new Filesystem)->copyDirectory(__DIR__.'/../../stubs/default/resources/views/components', resource_path('views/components'));

    copy(__DIR__.'/../../stubs/default/resources/views/dashboard.blade.php', resource_path('views/dashboard.blade.php'));

    // Components...
    (new Filesystem)->ensureDirectoryExists(app_path('View/Components'));
    (new Filesystem)->copyDirectory(__DIR__.'/../../stubs/default/App/View/Components', app_path('View/Components'));

    // Tests...
    (new Filesystem)->copyDirectory(__DIR__.'/../../stubs/default/tests/Feature', base_path('tests/Feature'));

    // Routes...
    copy(__DIR__.'/../../stubs/default/routes/web.php', base_path('routes/web.php'));
    copy(__DIR__.'/../../stubs/default/routes/auth.php', base_path('routes/auth.php'));

    // "Dashboard" Route...
    $this->replaceInFile('/home', '/dashboard', resource_path('views/welcome.blade.php'));
    $this->replaceInFile('Home', 'Dashboard', resource_path('views/welcome.blade.php'));
    $this->replaceInFile('/home', '/dashboard', app_path('Providers/RouteServiceProvider.php'));

    // Tailwind / Webpack...
    copy(__DIR__.'/../../stubs/default/tailwind.config.js', base_path('tailwind.config.js'));
    copy(__DIR__.'/../../stubs/default/webpack.mix.js', base_path('webpack.mix.js'));
    copy(__DIR__.'/../../stubs/default/resources/css/app.css', resource_path('css/app.css'));
    copy(__DIR__.'/../../stubs/default/resources/js/app.js', resource_path('js/app.js'));

    $this->info('Breeze scaffolding installed successfully.');
    $this->comment('Please execute the "npm install && npm run dev" command to build your assets.');
}

例えば追加されたルーティングを知りたい場合はweb.phpファイルに新たにルーティングの行が追加されているので、routesディレクトリの下にあるauth.phpファイルを見ることで確認できます。


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

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');

require __DIR__.'/auth.php';  //これが追加

認証に関するコントローラーはHttp¥Controllers¥Authの下に保存されています。

ユーザ登録画面やログイン画面を変更したい場合は、resources¥viewsの下にあるauth、componentsディレクトリのBladeファイルを更新することで行うことができます。

またユーザ登録時のバリデーションの内容などはapp¥Actions¥Fortifyフォルダの中のファイルで確認することができます。

追加されたルーティング

Breeze後に追加されたルーティングはルーティングファイルweb.phpと同じフォルダのapp¥routes¥auth.phpファイルに記述されています。


<?php

use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\ConfirmablePasswordController;
use App\Http\Controllers\Auth\EmailVerificationNotificationController;
use App\Http\Controllers\Auth\EmailVerificationPromptController;
use App\Http\Controllers\Auth\NewPasswordController;
use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\Auth\RegisteredUserController;
use App\Http\Controllers\Auth\VerifyEmailController;
use Illuminate\Support\Facades\Route;

Route::get('/register', [RegisteredUserController::class, 'create'])
                ->middleware('guest')
                ->name('register');

Route::post('/register', [RegisteredUserController::class, 'store'])
                ->middleware('guest');
//略

Laravelに設定されているルーティング情報を一括で確認したい場合はphp artisan route:listコマンドを実行することで確認することができます。

auth.phpファイルで追加された内容を確認することができます。

ルーティング情報はphp artisan route:list
ルーティング情報はphp artisan route:list

php artisan breeze:installを実行する前のルーティング情報は下記の通りです。Breezeにより複数のルーティングが追加されたことが比較によりはっきりわかります。


 % php artisan route:list
+--------+----------+----------+------+---------+------------+
| Domain | Method   | URI      | Name | Action  | Middleware |
+--------+----------+----------+------+---------+------------+
|        | GET|HEAD | /        |      | Closure | web        |
|        | GET|HEAD | api/user |      | Closure | api        |
|        |          |          |      |         | auth:api   |
+--------+----------+----------+------+---------+------------+

ユーザ登録画面

トップ画面に表示されているRegisterのリンクをクリックすると表示されるユーザ登録画面がどのような流れで表示されているのかを確認していきます。

リンクをクリックすると/registerへのアクセスが行われます。auth.phpファイルまたはphp artisan route:listの結果からpp\Http\Controllers\Auth\RegisteredUserController.phpファイルのcreateメソッドが実行されていることがわかります。


class RegisteredUserController extends Controller
{

    public function create()
    {
        return view('auth.register');
    }
    //略

createメソッドではviewファイルであるresource¥views¥auth¥register.blade.phpファイルを表示しています。ファイルではLaravel Componentとtailwindcssを使って入力フォームが記述されています。


<x-guest-layout>
    <x-auth-card>
        <x-slot name="logo">
            <a href="/">
                <x-application-logo class="w-20 h-20 fill-current text-gray-500" />
            </a>
        </x-slot>

        <!-- Validation Errors -->
        <x-auth-validation-errors class="mb-4" :errors="$errors" />

        <form method="POST" action="{{ route('register') }}">
            @csrf

            <!-- Name -->
            <div>
                <x-label for="name" :value="__('Name')" />

                <x-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus />
            </div>
//略

入力フォームの送信先は/registerになっているので/registerのPOSTリクエスト先であるRegisteredUserController.phpのstoreメソッドを確認します。storeメソッド内では入力フォームで入力したname, email, passwordのバリデーションが設定されています。nameは文字列の長さが最大255に設定されており、emailについては同じメールアドレスで複数のユーザ登録が行えないようにusersテーブルでuniqueのチェックを行い、emailのルールで@等メールアドレスの形式になっているかのチェックも行っています。パスワードでは8文字の制限がかけられておりそれ以下の文字数だと登録ができません。パスワードはシンプルなものでも登録が可能なので複雑な条件をつけたい場合は追加のバリデーションルールが必要となります。


public function store(Request $request)
{
    $request->validate([
        'name' => 'required|string|max:255',
        'email' => 'required|string|email|max:255|unique:users',
        'password' => 'required|string|confirmed|min:8',
    ]);

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

    event(new Registered($user));

    Auth::login($user);

    return redirect(RouteServiceProvider::HOME);
}

パスワードが一致しない場合は下記のようにメッセージが表示されます。

パスワードが一致しない場合のエラー
パスワードが一致しない場合のエラー

バリデーションを追加するとイベントが設定されておりこのイベントに対するリスナーを追加することでユーザ登録時の独自の処理を追加することができます。例えばリスナーにNotificaionを設定してSlack上でユーザが登録されたことを社内に通知するといった処理も追加することができます。

その後は登録したユーザのログイン処理(Auth::login($user))が行われRouteServiceProvider.phpの定数HOMEに設定した場所にリダイレクトされます。RouteServiceProvider.phpファイルを見るとHOMEは/dashboardであることがわかります。


class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to the "home" route for your application.
     *
     * This is used by Laravel authentication to redirect users after login.
     *
     * @var string
     */
    public const HOME = '/dashboard';
//略

/dashboardへのルーティングはphp artisan breeze:install時にweb.phpファイルに追加されています。


Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');

ミドルウェアのauthが設定されているためログインが完了していないユーザはdashboardへアクセスすることはできません。

ミドルウェアのauthの設定はKernel.phpファイルの中に記述されています。


protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,//ここ
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];

App\Http\Middleware\Authenticate.phpファイルを見るとredirectToメソッドのみ記述されています。その他のメソッドは継承しているMiddlewareのエイリアスであるIlluminate\Auth\Middleware\Authenticateの中に記述されています。


namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;

class Authenticate extends Middleware
{
    /**
     * Get the path the user should be redirected to when they are not authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string|null
     */
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
            return route('login');
        }
    }
}

redirectToメソッド内のroute(‘login’)関数の引数のloginはapp¥routes¥auth.phpファイルのルーティング設定時にnameメソッドで設定していた値です。そのnameはphp artisan route:listコマンド実行時に表示されるname列でも確認することができます。

Illuminate\Auth\Middleware\Authenticate.phpファイルではhandleメソッドが実行され、処理の詳細の説明は行いませんがユーザがログインしているかどうかのチェックが行われます。ユーザがログインしていない場合はredirectToメソッドにより/loginにリダイレクトされます。

ユーザのログアウト

ユーザのログアウトはユーザのログイン後に右上に表示される名前をクリックすると表示されるLog outをクリックするとドロップダウンメニューが表示されるLog outをクリックと実行できます。

ユーザのログアウト
ユーザのログアウト

ログアウトが行われるとトップページに戻ります。再度”/dashboard”にアクセスするとログイン画面が表示されます。このことからログアウトにより、ログインした時に与えられた許可情報がすべて削除されることがわかります。

ログアウトの処理も確認しておきましょう。

ログアウトのドロップダウンメニューはviews¥layouts¥navigation.blade.phpファイルの中に記述されています。


<!-- Authentication -->
<form method="POST" action="{{ route('logout') }}">
    @csrf

    <x-dropdown-link :href="route('logout')"
            onclick="event.preventDefault();
                        this.closest('form').submit();">
        {{ __('Log out') }}
    </x-dropdown-link>
</form>

route(‘logout’)へPOSTリクエストが送信されていることがわかります。route(‘logout’)関数の引数に設定されているloginはnameメソッドでルーティングにつかられた名前なのでapp¥routes¥auth.phpファイルで確認することができます。auth.phpからAuthenticatedSessionController.phpファイルのdestoryメソッドが実行されることがわかります。


Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])
                ->middleware('auth')
                ->name('logout');

destroyメソッドの中ではログアウト処理とセッションの処理が行われ、/(ルート)にリダイレクトされる処理になっています。


public function destroy(Request $request)
{
    Auth::guard('web')->logout();

    $request->session()->invalidate();

    $request->session()->regenerateToken();

    return redirect('/');
}

ユーザのログイン

ログインを行いたい場合は、右上のLoginリンクをクリックするかmiddlewareでauthが設定されているページ(/dashboard等)に直接アクセスすることで自動でログイン画面にリダイレクトされます。

ユーザのログイン
ユーザのログイン

ログイン画面ではメールアドレスとパスワードを入れる必要があります。Loginボタンを押すと入力した値のチェックが行われます。

ユーザログイン画面
ユーザログイン画面

もし、入力した値に間違いがある場合は、エラーメッセージが表示されます。These credentials do not match our recodes.(登録されている情報と異なります)

ログインに失敗した場合
ログインに失敗した場合

またログインに何度も失敗してしまうと一定時間ログインが行えなくなります。

Too many login attempts. Please try again in 48seconds.(ログイン試行回数が多いので48秒後に再度実行してください)

ログインの複数回の失敗
ログインの複数回の失敗

ログインの処理がどのように行われているか確認していきましょう。Loginのリンクをクリックすると/loginページへ移動します。

/loginページにアクセスが行われるとapp¥routes¥auth.phpファイルからApp\Http\Controllers\Auth\AuthenticatedSessionControllerのcreateメソッドが実行されてることがわかります。


Route::get('/login', [AuthenticatedSessionController::class, 'create'])
                ->middleware('guest')
                ->name('login');

AuthenticatedSessionControllerのcreateメソッドではviewファイルであるresource¥views¥auth¥login.blade.phpファイルを表示しています。


public function create()
{
    return view('auth.login');
}

ユーザ登録画面のregister.blade.phpファイルと同様にLaravel Componentとtailwindcssを使ってログインの入力フォームが記述されています。


<form method="POST" action="{{ route('login') }}">

ログインフォームの送信先は/loginになっているのでapp¥routes¥auth.phpファイルからApp\Http\Controllers\Auth\AuthenticatedSessionControllerのstoreメソッドが実行されてることがわかります。


Route::post('/login', [AuthenticatedSessionController::class, 'store'])
                ->middleware('guest');

storeメソッドではLoginRequestクラスのauthenticateメソッドが実行されていることがわかります。


public function store(LoginRequest $request)
{
    $request->authenticate();

    $request->session()->regenerate();

    return redirect()->intended(RouteServiceProvider::HOME);
}

LoginRequestクラスはApp\Http\Requests\Authフォルダの中に保存されておりFormRequestを継承しています。FormRequestはカスタムリクエストクラスでrulesメソッドを記述することでバリデーションを実行することができます。バリデーションはstoreメソッドでtype-hintでLoginRequestを設定することで実行されます。storeメソッドの中にバリデーションの処理を記述する必要はありません。

FormRequestはphp artisan make:request クラス名で作成することができます。

class LoginRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'email' => 'required|string|email',
            'password' => 'required|string',
        ];
    }
//略

rulesメソッドで設定されているバリデーションを通過するとLoginRequest.phpファイル内のauthenticateメソッドの中でログイン処理が行われます。


public function authenticate()
{
    $this->ensureIsNotRateLimited();

    if (! Auth::attempt($this->only('email', 'password'), $this->filled('remember'))) {
        RateLimiter::>($this->throttleKey());

        throw ValidationException::withMessages([
            'email' => __('auth.failed'),
        ]);
    }

    RateLimiter::clear($this->throttleKey());
}

ensureIsNotRateLimitedメソッドではログインが失敗した回数を記録し5回を超えると一定時間ログインが行えなくするための処理が記述されています。RateLimiterのtooManyAttemptsの引数の5と設定されている値を変更すると入力間違いで一定時間ログインができなくなるまでの回数を多くすることも少なくすることもできます。


public function ensureIsNotRateLimited()
{
    if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
        return;
    }

    event(new Lockout($this));

    $seconds = RateLimiter::availableIn($this->throttleKey());

    throw ValidationException::withMessages([
        'email' => trans('auth.throttle', [
            'seconds' => $seconds,
            'minutes' => ceil($seconds / 60),
        ]),
    ]);
}

デフォルトではログインが複数回失敗して次のログインまでの時間は60に設定していますがRateLimiterのhitメソッドの第2引数に数字を設定することで時間を短くしたり長くしたりすることが可能です。


RateLimiter::hit($this->throttleKey());

LoginRequest.phpのhitメソッドには第2引数には何も設定されていませんが、Illuminate\Cache\RateLimiterのhitメソッド見ること第2引数に秒数を設定できることが確認できます。デフォルト値は60に設定されています。


public function hit($key, $decaySeconds = 60)
{
    $this->cache->add(
        $key.':timer', $this->availableAt($decaySeconds), $decaySeconds
    );

    $added = $this->cache->add($key, 0, $decaySeconds);

    $hits = (int) $this->cache->increment($key);

    if (! $added && $hits == 1) {
        $this->cache->put($key, 1, $decaySeconds);
    }

    return $hits;
}

ユーザのログイン処理はauthenticateメソッドの中にあるAuth::attempt()で行われます。入力したemailとpasswordとデータベースに保存されているemailとpasswordが一致すればログインは成功です。


public function authenticate()
{
    $this->ensureIsNotRateLimited();

    if (! Auth::attempt($this->only('email', 'password'), $this->filled('remember'))) {
        RateLimiter::>($this->throttleKey());

        throw ValidationException::withMessages([
            'email' => __('auth.failed'),
        ]);
    }

    RateLimiter::clear($this->throttleKey());
}

Auth::attemptがこのファイルを見ただけではどこで実行されているのかわかりにくいですが最終的にはIlluminate\Auth\SessionGuardのattemptメソッドが実行されます。SessionGuardが実行される流れを理解するためにはFacadeの理解が必要になります。/comment]

ログインに成功した場合は、RouteServiceProviderで設定されているHOMEにリダイレクトされます。


public function store(LoginRequest $request)
{

    $request->authenticate();

    $request->session()->regenerate();

    return redirect()->intended(RouteServiceProvider::HOME);
}

リダイレクト先は、ユーザ登録した直後にリダイレクトされた場所と同じ/dashboardに設定されています。


class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to the "home" route for your application.
     *
     * This is used by Laravel authentication to redirect users after login.
     *
     * @var string
     */
    public const HOME = '/dashboard';

ログイン画面の日本語化

ユーザログイン画面はデフォルトではLoginボタンは英語で日本語ではありません。日本語化したい場合の方法を確認していきます。

ユーザログイン画面
ユーザログイン画面

ログイン画面に関するviewファイルresoucecs¥views¥authの下に保存されているlogin.blade.phpファイルです。Loginボタンの要素のみ確認すると下記のように記述されています。LOGINという文字列の変わりに{{ __(‘Log in’) }}と記述されています。


<x-button class="ml-3">
    {{ __('Log in') }}
</x-button>

ログインという文字に変更するため直接下記のように変更することができます。


<x-button class="ml-3">
    ログイン
</x-button>

ブラウザで確認すると更新した箇所が日本語になっていることを確認することができます。

ログインボタンの確認
ログインボタンの確認

再度login.blade.phpファイルの中身を確認するとLoginだけではなくpasswordもForgot your password等の文字にも{{ __(‘XXXXX’) }}で囲まれています。{ __(‘XXXXX’) }}で囲まれた文字列は直接文字を上書きしなくても設定ファイルを作成することで英語から日本語へ変更することができます。日本語ではなく中国語やフランス後にも変更することができます。Laravel Breezeにも多言語化機能が備わっています。

config¥app.phpファイルのlocale設定がデフォルトでは英語のenに設定されてますが日本語を表すjaに変更します。


'locale' => 'ja',

jaに変更後、resources¥langの下にja.jsonのJsonファイルを作成します。このファイルによって{ __(‘XXXXX’) }}のXXXXXに入力されている英語に対応した日本語を設定していきます。


{
  "Log in": "ログイン",
  "Password": "パスワード",
  "Email": "メールアドレス",
  "Forgot your password?": "パスワードをお忘れですか?",
  "Remember me": "パスワードを保存する"
}

設定後に再度ログイン画面を確認します。ja.jsonに設定した日本語が表示されれば設定ファイルによる日本語化は正常に動作しています。

ja.jsonファイルによる日本語化
ja.jsonファイルによる日本語化

ログイン画面ではなくユーザ登録画面も日本語かしたい場合は以下のようにja.jsonファイルに記述することで実現可能です。


{
  "Log in": "ログイン",
  "Password": "パスワード",
  "Email": "メールアドレス",
  "Forgot your password?": "パスワードをお忘れですか?",
  "Remember me": "パスワードを保存する",
  "Name": "名前",
  "Confirm Password":"パスワードの確認",
  "Already registered?":"登録済ですか?",
  "Register":"登録"
}

ログインIDをEmailからNameに変更

Breezeのログインではデフォルトではメールアドレスとパスワードを利用してログインを行うことができます。会社によっては個人のメールアドレスは持たない、社員は個別のメールアドレスを持っているが派遣社員や外注、パートやバイトの人はメールアドレスを持っていないということもあります。そのような場合にメールアドレスではなくユーザ名によってログインすることも可能です。

Http¥Controllers¥Authフォルダに下にログイン認証の処理を行うAuthenticatedSessionController.phpファイルがあります。実際の処理はLoginRequest.phpファイルに記述されているのでApp\Http\Requests\Auth\LoginRequestファイルを開きます。ファイルの各所にemailという文字列を確認することができます。例えばログイン時のバリデーションルールは下記のように設定されています。ルールではemailは必須、文字列、emailのXX@XXのような形になっているかチェックを行っています。


public function rules()
{
    return [
        'email' => 'required|string|email',
        'password' => 'required|string',
    ];
}

emailではなくusersテーブルのname列を利用してログインを行うように変更を行うのでrulesメソッドの中身をemailからnameに変更します。nameではバリデーションルールのemailは必要ではないので削除してください。


public function rules()
{
    return [
        'name' => 'required|string',
        'password' => 'required|string',
    ];
}

※authenticate、ensureIsNotRateLimited、throttleKeyメソッドの中のemailをnameに変更してください。合計4箇所変更を行います。

ログイン画面のviewファイルであるresources¥views¥authのlogin.blade.phpファイルの更新も必要となります。typeにemailが設定されているのでブラウザの機能により、XXX@XXXのemailの形式でない場合にエラーが表示されログイン処理が行われません。


<!-- Email Address -->
<div>
    <x-label for="email" :value="__('Email')" />

    <x-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
</div>

emailをnameに変更しています。typeはemailからtextへと変更。x-labelのvalueのコロンを削除してログイン名と設定しています。


<!-- Email Address -->
<div>
    <x-label for="name" value="ログイン名" />

    <x-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus />
</div>

設定後はログイン画面がEmailからユーザ名に変更されます。ユーザ登録時に指定したnameでログインできることを確認してください。

ユーザ名でログイン
ユーザ名でログイン