【Laravel】パスワードリセットをメールアドレスの入力なしで実装する方法

技術メモ

今回はメールアドレスを入力せずにパスワードを変更する方法について、わかりやすく説明していきます。

また、なるべくコピペで実装できるようにコードをまるごと掲載していきます!

 

Laravelにデフォルトで実装されているパスワードリセット機能は非常に便利ですが、パスワード再設定画面でもう一度メールアドレスを入力する必要があり、二度手間です(一応自動で入力してくれますが)。

 

パスワード再設定画面

 

そこで、今回はメールアドレスを入力させずにパスワードの入力のみでパスワードの再設定を行います。

 

今回実装するメールアドレス変更機能の流れは以下の通りです。

ほとんどLaravelデフォルトのパスワードリセット機能を使います。

 

①ユーザーがメールアドレスを入力

②入力したメールアドレスあてにパスワード再設定メールを送信する

③メールのリンクからパスワード再設定フォームに遷移

新しいパスワードのみを入力して、パスワードを再設定する

 

それではいきましょう!

 

開発環境

  • MacBook Pro (macOS Catalina バージョン10.15.2)
  • PHP 7.3.9
  • Laravel Framework 6.13.1

Composerはすでにインストールしているとします。

 

メールアドレス変更の前準備

すでにプロジェクトを作成している場合は省略してください。

 

新規プロジェクト作成

まずは新規プロジェクトを作成します。

ターミナル

composer create-project --prefer-dist laravel/laravel PasswordResetWithoutEmailSample

 

 

プロジェクトのカレントディレクトリに移動して、ローカル開発サーバを立ち上げます。

ターミナル

php artisan serve

 

.envのAPP_URLにポート番号を追加しておいてください。

APP_URL=http://localhost:8000

 

http://127.0.0.1:8000にアクセスします。

ページが正常に表示されていればOKです。

 

認証機能作成

コマンドで簡単に認証機能を作成します。

Laravel 6.0以降は認証機能実装手順が変更されているので注意してください。

 

  • Laravel 5.8以前

ターミナル

php artisan make:auth

 

  • Laravel 6.0以降

ターミナル

composer require laravel/ui --dev
php artisan ui vue --auth
npm install && npm run dev

 

認証機能が作成されると右上にLOGIN と REGISTERが追加されます。

 

マイグレーションしてテーブル作成&テストデータ挿入

シーダーファイルを作成し、以下のように修正します。

 

ターミナル

php artisan make:seeder UsersTableSeeder

 

UsersTableSeeder.php

<?php 
use Illuminate\Database\Seeder; 

class UsersTableSeeder extends Seeder 
{ 
    public function run() { DB::table('users')->insert([
            [
                'name'           => '田中太郎',
                'email'          => 'tanaka@example.com',
                'password'       => Hash::make('password'),
            ],
        ]);
    }
}

 

DatabaseSeeder.phpを以下のように修正します。

<?php 

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UsersTableSeeder::class);
    }
}

 

テーブルを作成して、データを挿入します。

ターミナル

php artisan migrate:fresh --seed

 

DBの状態はこんな感じです。

 

LOGINからメールアドレスとパスワードを入力すると無事ログインできました。

 

これで準備は完了です。

 

メールの受信テストの準備

メールを送信するためメールサーバーが必要ですが、今回はテスト送信で済ませるので、MailHogを使用します。

MailHogはメールのテストツールです。

 

MailHogをインストール&起動します。

ターミナルで

brew install mailhog
brew services start mailhog

 

Laravel側は.envの設定を以下のように修正します。

MAIL_DRIVER=smtp
# MAIL_HOST=smtp.mailtrap.io
MAIL_HOST=localhost
# MAIL_PORT=2525
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=sender@example.com
MAIL_FROM_NAME="${APP_NAME}"

 

.envの設定を変更したのでキャッシュをクリアしておきます。

ターミナル

php artisan config:cache

 

以下のURLにアクセスしてMailHogの画面が表示されれば成功です。

http://localhost:8025/

 

メールアドレス入力なしのパスワード再設定機能を実装する

それではパスワード再設定画面からメールアドレスフィールドを消していきます。

 

まずはパスワード再設定の流れを確認します。

「Forget Your Password?」をクリックします。

 

DBに登録しているメールアドレスを入力して、パスワード再設定メールを送信します。

 

MailHogで届いたメールを確認します。

 

「Reset Password」ボタンをクリックするとパスワード再設定画面に遷移します。

 

上記がデフォルトの流れになります。

この時のパスワード再設定画面のURLを確認すると、

http://localhost:8000/password/reset/e4fdec64596bab3471c1b1382a075636f1196103404e269c533948a1b8081165?email=tanaka%40example.com

 

このようにトークン+メールアドレスとなっています。

このURLパラメータを見て、パスワード再設定画面のreset.blade.phpに値を渡しています。

 

したがって、reset.blade.phpのメールアドレス入力フォームのtype属性をhiddenに設定することでメールアドレスフォームを非表示にすることが可能です。

 

具体的には以下のように修正します。

reset.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Reset Password') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('password.update') }}">
                        @csrf

                        <input type="hidden" name="token" value="{{ $token }}">

                        <div class="form-group row">
                            <!-- <label for="email"
                                class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label> -->

                            <div class="col-md-6">
                                <input id="email" type="hidden"
                                    class="form-control @error('email') is-invalid @enderror" name="email"
                                    value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus>

                                @error('email')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password"
                                class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password"
                                    class="form-control @error('password') is-invalid @enderror" name="password"
                                    required autocomplete="new-password">

                                @error('password')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password-confirm"
                                class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>

                            <div class="col-md-6">
                                <input id="password-confirm" type="password" class="form-control"
                                    name="password_confirmation" required autocomplete="new-password">
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Reset Password') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

メールアドレス入力フォームは非表示にしているので、E-Mail Addressのラベルも非表示にしてください。

 

これでパスワードを変更してみます。

テーブル初期状態は以下の通りです。

 

パスワード再設定画面ではメールアドレスが非表示になっています。

 

パスワードを入力して再設定します。

その後、テーブルを確認してみます。

 

パスワードのハッシュ値が変わり、 更新日が入力されているのでパスワードが正常に更新されたことがわかります。

 

 

今回はLaravelにてメールアドレスの入力なしでパスワードを更新する方法について解説しました。

他にも解説して欲しい内容があれば、是非ともコメント欄やお問い合わせからメッセージをください!

それでは!

技術メモ
スポンサーリンク
スポンサーリンク
とんでもくんをフォローする
やばブロ!

コメント