【Laravelチュートリアル】 STEP6 ログイン認証と利用制限

投稿日: 2024.02.14

これまで、Web開発の一通りの流れを学んできました。

この章では、ログイン機能とプログラムの利用制限について学んでいきましょう。

1.ログイン設定

実は、Laravelをインストールしたときからログインに関するものは標準で準備されています。

これらを利用するだけだと非常に簡単になってしまうため、少し実用的なログイン認証を実装していきます。

現在のログイン、ソーシャルログインやSMS承認などログインの方法が多岐に渡ります。

そこでLaravel標準のログインを利用せず、Laravel Fortifyを利用していきます。

Laravel Fortityは、フロントエンドにとらわれないLaravelの認証バックエンドの実装です。Fortifyは、ログイン、ユーザー登録、パスワードのリセット、メールの検証など、Laravelの認証機能をすべて実装するために必要なルートとコントローラを登録します。  
https://readouble.com/laravel/10.x/ja/fortify.html

ログイン認証の設定を確認しましょう。

// project/config/auth.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session"
    |
    */

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

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

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

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that each reset token will be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Password Confirmation Timeout
    |--------------------------------------------------------------------------
    |
    | Here you may define the amount of seconds before a password confirmation
    | times out and the user is prompted to re-enter their password via the
    | confirmation screen. By default, the timeout lasts for three hours.
    |
    */

    'password_timeout' => 10800,

];

ここにどのようにログインしていくかを設定しています。今回はなにも変更はありません。

データベースの設定も確認しておきましょう。

// project/database/migrations/2014_10_12_000000_create_users_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', 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();
        });
    }

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

laravelがユーザの定義も準備してくれています。

2.Laravel Fortifyを設定

パッケージをインストール

composer require laravel/fortify

コマンドを使用してFortifyのリソースを公開します。

php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"
root@537ae07b9b21:/var/workspace/project# php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"

   INFO  Publishing assets.  

  Copying file [vendor/laravel/fortify/stubs/fortify.php] to [config/fortify.php] ............................................................. DONE
  Copying file [vendor/laravel/fortify/stubs/CreateNewUser.php] to [app/Actions/Fortify/CreateNewUser.php] .................................... DONE
  Copying file [vendor/laravel/fortify/stubs/FortifyServiceProvider.php] to [app/Providers/FortifyServiceProvider.php] ........................ DONE
  Copying file [vendor/laravel/fortify/stubs/PasswordValidationRules.php] to [app/Actions/Fortify/PasswordValidationRules.php] ................ DONE
  Copying file [vendor/laravel/fortify/stubs/ResetUserPassword.php] to [app/Actions/Fortify/ResetUserPassword.php] ............................ DONE
  Copying file [vendor/laravel/fortify/stubs/UpdateUserProfileInformation.php] to [app/Actions/Fortify/UpdateUserProfileInformation.php] ...... DONE
  Copying file [vendor/laravel/fortify/stubs/UpdateUserPassword.php] to [app/Actions/Fortify/UpdateUserPassword.php] .......................... DONE
  Copying directory [vendor/laravel/fortify/database/migrations] to [database/migrations] ..................................................... DONE

たくさんファイルがコピーされます。

migrationも実行しましょう。

php artisan migrate

2段階認証用のカラム(項目)がusersテーブルに追加されます。

ルートも多く追加されています。

  GET|HEAD  api/user ................................................................................................................................. 
  GET|HEAD  forgot-password .................................................. password.request › Laravel\Fortify › PasswordResetLinkController@create
  POST      forgot-password ..................................................... password.email › Laravel\Fortify › PasswordResetLinkController@store
  GET|HEAD  login .................................................................... login › Laravel\Fortify › AuthenticatedSessionController@create
  POST      login ............................................................................. Laravel\Fortify › AuthenticatedSessionController@store
  POST      logout ................................................................. logout › Laravel\Fortify › AuthenticatedSessionController@destroy
  GET|HEAD  register .................................................................... register › Laravel\Fortify › RegisteredUserController@create
  POST      register ................................................................................ Laravel\Fortify › RegisteredUserController@store
  POST      reset-password ........................................................... password.update › Laravel\Fortify › NewPasswordController@store
  GET|HEAD  reset-password/{token} ................................................... password.reset › Laravel\Fortify › NewPasswordController@create
  GET|HEAD  sanctum/csrf-cookie .................................................... sanctum.csrf-cookie › Laravel\Sanctum › CsrfCookieController@show
  GET|HEAD  two-factor-challenge ................................. two-factor.login › Laravel\Fortify › TwoFactorAuthenticatedSessionController@create
  POST      two-factor-challenge ..................................................... Laravel\Fortify › TwoFactorAuthenticatedSessionController@store
  GET|HEAD  user/confirm-password ............................................................... Laravel\Fortify › ConfirmablePasswordController@show
  POST      user/confirm-password ........................................... password.confirm › Laravel\Fortify › ConfirmablePasswordController@store
  GET|HEAD  user/confirmed-password-status .......................... password.confirmation › Laravel\Fortify › ConfirmedPasswordStatusController@show
  POST      user/confirmed-two-factor-authentication ......... two-factor.confirm › Laravel\Fortify › ConfirmedTwoFactorAuthenticationController@store
  PUT       user/password ......................................................... user-password.update › Laravel\Fortify › PasswordController@update
  PUT       user/profile-information ......................... user-profile-information.update › Laravel\Fortify › ProfileInformationController@update
  POST      user/two-factor-authentication ............................. two-factor.enable › Laravel\Fortify › TwoFactorAuthenticationController@store
  DELETE    user/two-factor-authentication .......................... two-factor.disable › Laravel\Fortify › TwoFactorAuthenticationController@destroy
  GET|HEAD  user/two-factor-qr-code ............................................ two-factor.qr-code › Laravel\Fortify › TwoFactorQrCodeController@show
  GET|HEAD  user/two-factor-recovery-codes ................................ two-factor.recovery-codes › Laravel\Fortify › RecoveryCodeController@index
  POST      user/two-factor-recovery-codes ............................................................ Laravel\Fortify › RecoveryCodeController@store
  GET|HEAD  user/two-factor-secret-key ................................... two-factor.secret-key › Laravel\Fortify › TwoFactorSecretKeyController@show
php artisan route:listのコマンドを実行するとルート一覧が確認できます。

ログイン関連の設定は、App\Providers\FortifyServiceProviderから行います。

configにProviderを追加します。

// project/config/app.php
    'providers' => [
    // ..

        /*
         * Package Service Providers...
         */
        App\Providers\FortifyServiceProvider::class,
     ]

エラーが出る場合は、php artisan cache:clearをしてみてください、

configを確認する。

// project/config/fortify.php
<?php

use Laravel\Fortify\Features;

return [

    /*
    |--------------------------------------------------------------------------
    | Fortify Guard
    |--------------------------------------------------------------------------
    |
    | Here you may specify which authentication guard Fortify will use while
    | authenticating users. This value should correspond with one of your
    | guards that is already present in your "auth" configuration file.
    |
    */

    'guard' => 'web',

    /*
    |--------------------------------------------------------------------------
    | Fortify Password Broker
    |--------------------------------------------------------------------------
    |
    | Here you may specify which password broker Fortify can use when a user
    | is resetting their password. This configured value should match one
    | of your password brokers setup in your "auth" configuration file.
    |
    */

    'passwords' => 'users',

    /*
    |--------------------------------------------------------------------------
    | Username / Email
    |--------------------------------------------------------------------------
    |
    | This value defines which model attribute should be considered as your
    | application's "username" field. Typically, this might be the email
    | address of the users but you are free to change this value here.
    |
    | Out of the box, Fortify expects forgot password and reset password
    | requests to have a field named 'email'. If the application uses
    | another name for the field you may define it below as needed.
    |
    */

    'username' => 'email',

    'email' => 'email',

    /*
    |--------------------------------------------------------------------------
    | Lowercase Usernames
    |--------------------------------------------------------------------------
    |
    | This value defines whether usernames should be lowercased before saving
    | them in the database, as some database system string fields are case
    | sensitive. You may disable this for your application if necessary.
    |
    */

    'lowercase_usernames' => true,

    /*
    |--------------------------------------------------------------------------
    | Home Path
    |--------------------------------------------------------------------------
    |
    | Here you may configure the path where users will get redirected during
    | authentication or password reset when the operations are successful
    | and the user is authenticated. You are free to change this value.
    |
    */

    'home' => '/',

    /*
    |--------------------------------------------------------------------------
    | Fortify Routes Prefix / Subdomain
    |--------------------------------------------------------------------------
    |
    | Here you may specify which prefix Fortify will assign to all the routes
    | that it registers with the application. If necessary, you may change
    | subdomain under which all of the Fortify routes will be available.
    |
    */

    'prefix' => '',

    'domain' => null,

    /*
    |--------------------------------------------------------------------------
    | Fortify Routes Middleware
    |--------------------------------------------------------------------------
    |
    | Here you may specify which middleware Fortify will assign to the routes
    | that it registers with the application. If necessary, you may change
    | these middleware but typically this provided default is preferred.
    |
    */

    'middleware' => ['web'],

    /*
    |--------------------------------------------------------------------------
    | Rate Limiting
    |--------------------------------------------------------------------------
    |
    | By default, Fortify will throttle logins to five requests per minute for
    | every email and IP address combination. However, if you would like to
    | specify a custom rate limiter to call then you may specify it here.
    |
    */

    'limiters' => [
        'login' => 'login',
        'two-factor' => 'two-factor',
    ],

    /*
    |--------------------------------------------------------------------------
    | Register View Routes
    |--------------------------------------------------------------------------
    |
    | Here you may specify if the routes returning views should be disabled as
    | you may not need them when building your own application. This may be
    | especially true if you're writing a custom single-page application.
    |
    */

    'views' => true,

    /*
    |--------------------------------------------------------------------------
    | Features
    |--------------------------------------------------------------------------
    |
    | Some of the Fortify features are optional. You may disable the features
    | by removing them from this array. You're free to only remove some of
    | these features or you can even remove all of these if you need to.
    |
    */

    'features' => [
        Features::registration(),
        Features::resetPasswords(),
        // Features::emailVerification(),
        Features::updateProfileInformation(),
        Features::updatePasswords(),
        Features::twoFactorAuthentication([
            'confirm' => true,
            'confirmPassword' => true,
            // 'window' => 0,
        ]),
    ],

];
'home' => '/'だけ変更します。これはログイン、新規作成後のリダイレクト先を設定しています。

3.ユーザー認証

ログイン画面の設定を行います。

<?php

namespace App\Providers;

use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Laravel\Fortify\Fortify;

class FortifyServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Fortify::createUsersUsing(CreateNewUser::class);
        Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
        Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);

        RateLimiter::for('login', function (Request $request) {
            $throttleKey = Str::transliterate(Str::lower($request->input(Fortify::username())).'|'.$request->ip());

            return Limit::perMinute(5)->by($throttleKey);
        });

        RateLimiter::for('two-factor', function (Request $request) {
            return Limit::perMinute(5)->by($request->session()->get('login.id'));
        });

        Fortify::loginView(function () {
            return view('auth.login');
        });
    }
}
Fortify::loginViewでログイン画面のviewを設定します。

テスト用のユーザーデータを作成します。

php artisan make:seeder UsersTableSeeder
// project/database/seeders/UsersTableSeeder.php
<?php

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        User::updateOrCreate(['email' => 'local@example.com'], ['name' => 'ララベル 太郎', 'password' => Hash::make('passw@rd'), 'email_verified_at' => now()]);
    }
}

ログイン画面を作成します。

// project/resources/views/auth/login.blade.php
@extends('layouts.app')

@section('content')
    <div class="login pt-5">
        <div class="card mx-auto" style="max-width: 565px;">
            <div class="card-body">
                <h1 class="text-center">Login</h1>
    
                <form action="{{ route('login') }}" method="POST">
                    @csrf
                    <div class="mb-3">
                        <label for="">ログインID</label>
                        <input type="email" name="email" class="form-control" value="{{ old('email') }}">
                        @error('email')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <div class="mb-3">
                        <label for="">パスワード</label>
                        <input type="password" name="password" class="form-control">
                        @error('password')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <div class="d-grid gap-2 col-6 mx-auto">
                        <button type="submit" class="btn btn-primary">ログイン</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
@endsection

4.ユーザの登録

ログイン画面の作成と同様にユーザー作成画面の登録をします。

// project/app/Providers/FortifyServiceProvider.php
use Laravel\Fortify\Fortify;

/**
 * 全アプリケーションサービスの起動処理
 */
public function boot(): void
{
    // ...
    Fortify::registerView(function () {
        return view('auth.register');
    });
}

レイアウトを作成する。

// project/resources/views/auth/register.blade.php
@extends('layouts.app')

@section('content')
    <div class="login pt-5">
        <div class="card m-auto" style="max-width: 565px;">
            <div class="card-body">
                <h1 class="text-center">新規作成</h1>
    
                <form action="{{ route('register') }}" method="POST">
                    @csrf
                    <div class="mb-3">
                        <label for="">名前</label>
                        <input type="name" name="name" class="form-control" value="{{ old('name') }}">
                        @error('name')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <div class="mb-3">
                        <label for="">ログインID</label>
                        <input type="email" name="email" class="form-control" value="{{ old('email') }}">
                        @error('email')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <div class="mb-3">
                        <label for="">パスワード</label>
                        <input type="password" name="password" class="form-control">
                        @error('password')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                        <label for="">パスワード確認</label>
                        <input type="password" name="password_confirmation" class="form-control" placeholder="もう一度パスワードを入力してください">
                        @error('password_confirmation')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <div class="d-grid gap-2 col-6 mx-auto">
                        <button type="submit" class="btn btn-primary">新規作成</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
@endsection

ユーザー登録のカスタマイズは、App\Actions\Fortify\CreateNewUserから変更ができます。

5.パスワードリセット

パスワードリセット用の画面を登録します。

// project/app/Providers/FortifyServiceProvider.php
use Laravel\Fortify\Fortify;

/**
 * 全アプリケーションサービスの起動処理
 */
public function boot(): void
{
    Fortify::requestPasswordResetLinkView(function () {
        return view('auth.forgot-password');
    });

    // ...
}
// project/resources/views/auth/forgot-password.blade.php
@extends('layouts.app')

@section('content')
    <div class="login pt-5">
        <div class="card m-auto" style="max-width: 565px;">
            <div class="card-body">
                <h1 class="text-center">メールを確認</h1>
                <p class="text-center text-info">リセット用のメールが届くまで数分お待ちください。メール内のリンクをクリックしてください。リンクの有効期限は1時間です。</p>
                <form action="{{ route('password.email') }}" method="POST">
                    @csrf
                    <div class="mb-3">
                        <label for="">ログインID</label>
                        <input type="email" name="email" class="form-control" placeholder="あなたのメールアドレスを入力してください">
                        @error('email')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <div class="d-grid gap-2 col-6 mx-auto">
                        <button type="submit" class="btn btn-primary">メールを送信</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
@endsection

メールを送信するため、.envの設定が必要です。

今回は、テストのためlogでメール内容を確認します。

MAIL_MAILER=log
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=info@example.com
MAIL_FROM_NAME="${APP_NAME}"
MAIL_MAILERMAIL_FROM_ADDRESSを設定すればとりあえずOKです。

logからリンクを探します。以下のようなリンクが生成されるはずです。

http://localhost:8000/reset-password/14e04df058dd9e855b6e657092a58ecf841d2d14a5a6f4b78fedea5fba20d442?email=local%40example.com

パスワードリセットの画面を作成する

// project/app/Providers/FortifyServiceProvider.php
use Laravel\Fortify\Fortify;
use Illuminate\Http\Request;

/**
 * 全アプリケーションサービスの起動処理
 */
public function boot(): void
{
    Fortify::resetPasswordView(function (Request $request) {
        return view('auth.reset-password', ['request' => $request]);
    });

    // ...
}
// project/resources/views/auth/reset-password.blade.php
@extends('layouts.app')

@section('content')
    <div class="login pt-5">
        <div class="card m-auto" style="max-width: 565px;">
            <div class="card-body">
                @if (session('status'))
                    <div class="mb-3 alert alert-success" role="alert">
                        {{ session('status') }}
                    </div>
                @endif
                <h1 class="text-center">パスワードをリセットします。</h1>
                <p class="text-center text-info"></p>
                <form action="{{ route('password.update') }}" method="POST">
                    @csrf
                    <input type="hidden" name="token" value="{{ request()->route('token') }}">
                    <div class="mb-3">
                        <label for="">ログインID</label>
                        <input type="email" name="email" class="form-control" value="{{ old('email') }}">
                        @error('email')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <div class="mb-3">
                        <label for="">パスワード</label>
                        <input type="password" name="password" class="form-control">
                        @error('password')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                        <label for="">パスワード確認</label>
                        <input type="password" name="password_confirmation" class="form-control" placeholder="もう一度パスワードを入力してください">
                        @error('password_confirmation')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <div class="d-grid gap-2 col-6 mx-auto">
                        <button type="submit" class="btn btn-primary">パスワードをリセットする</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
@endsection

ログイン画面にステータスを表示する項目を追加する

@extends('layouts.app')

@section('content')
    <div class="login pt-5">
        <div class="card m-auto" style="max-width: 565px;">
            <div class="card-body">
                @if (session('status'))
                    <div class="mb-3 alert alert-success" role="alert">
                        {{ session('status') }}
                    </div>
                @endif
                <h1 class="text-center">Login</h1>
    
                <form action="{{ route('login') }}" method="POST">
                    @csrf
                    <div class="mb-3">
                        <label for="">ログインID</label>
                        <input type="email" name="email" class="form-control" value="{{ old('email') }}">
                        @error('email')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <div class="mb-3">
                        <label for="">パスワード</label>
                        <input type="password" name="password" class="form-control">
                        @error('password')
                            <div class="invalid-feedback d-block">{{ $message }}</div>
                        @enderror
                    </div>
                    <p>
                        <a href="{{ route('password.request') }}">パスワードをお忘れですか?</a>
                    </p>
                    <div class="d-grid gap-2 col-6 mx-auto">
                        <button type="submit" class="btn btn-primary">ログイン</button>
                    </div>
                </form>
                <hr>
                
                <div class="d-grid gap-2 col-6 mx-auto">
                    <a href="{{ route('register') }}" class="btn btn-secondary">新規作成</a>
                </div>
                
            </div>
        </div>
    </div>
@endsection

これで、ログイン関連の機能が一通り実装できました。

6.ログアウト

headerにログイン/ログインアウトを追加する

// project/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">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{ config('app.name') }}</title>

    {{-- ここは、画面に表示されません --}}
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
    {{-- ここから画面に表示されます。 --}}
    <header class="navbar">
        <div class="container-fluid">
          <h1 class="navbar-brand">{{ config('app.name') }}</h1>

            @auth
                <form method="post" action="{{ route('logout') }}">
                    @csrf
                    <button type="submit" class="btn">ログアウト</button>
                </form>
            @endauth

            @guest
                <a href="{{ route('login') }}" class="btn">ログイン</a>
            @endguest
        </div>
    </header>
    <div>
    <main>
        <div class="container">
            @yield('content')
        </div>
    </main>
    <footer>
        <p>© 2024 laravelチュートリアル</p>
    </footer>
    </div>
</body>
</html>

7.利用制限をする

投稿一覧、編集、削除を一通りログイン者のみに制限します。

基本的な利用制限はRouteで制限します。

// route/web.php

Route::middleware('auth')->group(function() {
    Route::get('/post', [PostController::class, 'index'])->name('post.index');
    Route::get('/post/create', [PostController::class, 'create'])->name('post.create');
    Route::post('/post/create', [PostController::class, 'store']);
    Route::get('/post/{id}', [PostController::class, 'edit'])->name('post.edit');
    Route::post('/post/{id}', [PostController::class, 'update']);
    Route::get('/post/{id}/delete', [PostController::class, 'destroy'])->name('post.destroy');
});
middleware('auth')を付けることでログイン者のみに制限できます。groupでルートをまとめることも可能です。もちろんルートに個別で設定することもできます。

8.未ログイン者(ゲスト)のページを作成

ゲストのための詳細ページを作成します。

投稿管理とわかるためにArticleControllerを作成します。

 php artisan make:controller ArticleController
// app/Http/Controllers/ArticleController.php
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class ArticleController extends Controller
{
    /**
     * 投稿詳細ページ
     * 
     * @param string $id
     * @return View
     */
    public function show($id)
    {
        $post = Post::find($id);

        if ($post == null) {
            abort(404);
        }

        return view('article.show', [
            'post' => $post
        ]);
    }
}
// route/web.php
Route::get('article/{id}', [ArticleController::class, 'show'])->name('article.show');
@extends('layouts.app')

@section('content')
    <article>
        <h1 class="py-3">{{ $post->title }}</h1>
        {!! nl2br($post->content) !!}
    </article>
@endsection

一覧のページにもリンクを設置していきます。

@extends('layouts.app')

@section('content')
    <h1>Hello World</h1>
    <div class="mb-3">
        <div class="row row-cols-2 g-3">
            @foreach($pagination as $post)
                <div class="col">
                    <div class="card h-100">
                        <div class="card-body">
                            <h5 class="card-title">{{ $post->title }}</h5>
                            <p class="card-text">{{ Str::limit($post->content) }}</p>
                            <div class="text-end">
                                <a href="{{ route('article.show', ['id' => $post->id]) }}" class="btn btn-primary">詳細へ</a>
                            </div>
                        </div>
                    </div>
                </div>
            @endforeach
        </div>
    </div>
    <div class="mb-3">
        {{ $pagination->links() }}
    </div>
@endsection

今回はログインについて学びました。

Fortifyを利用することで、APIログインや2段階認証など簡単に実装ができるようになるので今回はこれを利用してみました。

また、ルートで利用制限の方法についても理解しましたね。

これで大分Webサイトらしくなってきました。