こんにちは。

今回はLaravelのパスワードリセットやら通知のメールなどの小難しい機能について。

「make:auth」コマンド1つで、デフォルトでこう言ったものがサクッと作れるのは非常にありがたいですが、もうちょっと気の利いた感じで作りたい・・・。

とか思ってカスタマイズをし出すと、毎度、毎度沼にハマってしまうので。。

自分用に「このままコピペしたら基本OK」みたいなメモです。

誰かの参考にもなれば幸いです。

前提たち

今回、登場する方々を先にご紹介。

 1:登場する方たち

関係するView(テンプレート)たち

/resources/views/auth/passwords/  の

email.blade.php → アドレスを入力してもらうフォームがあるビュー。(以下:「アドレス入力のビュー」と呼びます)

reset.blade.php → 送られてきたメールのリンクから飛んできて、新しいパスワードを入力するフォームがあるビュー(以下:「リセットのビュー」と呼びます)

reset_expired.blade.php → メールに添付されたリンクの有効期限が切れてる場合に表示するビュー。これは自作してる。(以下:「トークンエラーのビュー」と呼びます)

/resources/views/auth/emails/ の

reset_password.blade.php → 送られてくるメール本文をカスタマイズするためのビュー。この内容が送られてくる。これも自作。(以下:「メールのテンプレート」と呼びます)

コントローラー(処理のカスタマイズの本丸)たち

app/Http/Controllers/Auth/ の

ForgotPasswordController.php → 「アドレス入力のビュー」からアドレスを受け取り・処理して「メールのテンプレート」を送るためのコントローラー。

(以下:「Forgotパスコントローラー」と呼びます)

ResetPasswordController.php → 「リセットのビュー」で入力されたパスワードをなんやかんやするコントローラー

(以下:「リセットコントローラー」と呼びます)

その他

Userモデル → 自作して、カスタマイズした「メールのテンプレート」を使ってね。という処理を追加するために使う

app/Notifications/CustomResetPassword.php

 → Notificationsディレクトリも、CustomResetPassword.phpも自作してる。「メールのテンプレート」は本文の内容をカスタマイズできるが、メールの件名とかはこっちで。

いっぱい。。

 2:バージョンとどういう挙動を目指してるか

● バージョン: Laravel5.8 を使ってます。もっと新しければこんなに面倒じゃないのかも。

・Authや通知(Notifications)、メール(mails)などのディレクトリ・クラスの作成は済んでるものとします。

・各ビューのHTML等々、特に以下のようにフラッシュメッセージの表示ができるような設定も済みとします。

● 目指す挙動:

① 「アドレス入力のビュー」ではバリデーションをしつつ、メールを正常に送信した場合はフラッシュメッセージで完了のお知らせをする。

↓こんな感じで。

② 「メールのテンプレート」をカスタマイズして、本文・件名・メール下部の文言などを日本語に。

こんな感じに。↓

③ 「リセットのビュー」では、正常にパスワードの更新ができたならマイページにリダイレクトして完了のお知らせをフラッシュメッセージで。

また、トークンの有効期限が切れてる等で「リセットのビュー」が無効な場合は「トークンエラーのビュー」を表示する

こんな感じで。↓

2:いざ本題

では、ようやく本題に入ります。

 1:「アドレス入力のビュー」で完了のフラッシュメッセージを表示する。

これは「Forgotパスコントローラー」の、sendResetLinkEmai メソッドをオーバーライドする。らしい

【 ForgotPasswordController.php 】

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
use App\User;
use Illuminate\Database\QueryException;
class ForgotPasswordController extends Controller
{
    use SendsPasswordResetEmails;
    public function sendResetLinkEmail(Request $request)
    {
        $this->validateEmail($request);
        $response = $this->broker()->sendResetLink(
            $request->only('email')
        );
    // 正常に完了した場合
        if ($response == Password::RESET_LINK_SENT) {
            return back()->with('flash_message', 'メールを送信しました!');
        }
        // バリデーションエラーが発生した場合
        return back()
            ->withInput($request->only('email'))
            ->withErrors(['email' => 'メールを送信できませんでした。メールアドレスをご確認ください']);
    
    }
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }
}

● バリデーションエラーの部分・・・これが無いと、DBに存在しないメールアドレスが入力・送信された際に真っ白い画面になっちゃう。

● 正常にメールが送られた後、今回はリダイレクトバックをしてるがお好みで。

 2:メールのテンプレートのカスタマイズ

送られてくるメールのカスタマイズをしちゃう。

まずはapp/Notifications/CustomResetPassword.php

<?php
namespace App\Notifications;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;
class CustomResetPassword extends Notification
{
    /**
    * The password reset token.
    * 
    /** @var string */
    public $token;
    
    /**
     * Create a new notification instance.
     *
     * @param  string  $token
     * @return void
     */
    
    public function __construct($token)
    {
        $this->token = $token;
    }
    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }
    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    
        public function toMail($notifiable)
        {
            // パスワードリセットのリンクを生成
            $actionUrl = url('password/reset', $this->token);
            // ↓↓↓↓↓↓ カスタマイズしたメールテンプレートを使う処理 ↓↓↓↓↓↓
           
            return (new MailMessage)
                ->from('〇〇@△△.com', config('app.name')) // メールの送信元
                ->subject('パスワード再設定のご案内') // ここがメールの件名になる
                ->markdown('emails.reset-password', ['actionUrl' => $actionUrl]);        } // メール本文はこのビュー見にいけよ。ってこと
  
  // ↑↑↑↑↑↑↑↑↑↑↑↑ここまで↑↑↑↑↑↑↑↑↑↑↑↑↑↑
           
        
    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

これをパスワードリセット時に使うようにUserモデルに以下を追加。

   // 自作のパスワードリセットのメールテンプレートを使うようにお願いしちゃう
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new CustomResetPassword($token));
    }

そして、どんなメールの内容にするか、「メールのテンプレート」を編集していく。

こんにちは!
<br><br>
パスワードのリセットリクエストを受け付けました。以下のボタンをクリックしてパスワードをリセットしてください。
<br>
@component('mail::button', ['url' => $actionUrl])
    パスワードの再設定画面へ
@endcomponent
<br>
このリンクは30分間有効です。
<br>
よろしくお願いいたします。
<br>
ご注意:このメールに返信しないでください。

これでパスワードを忘れたユーザー(入力されたアドレス宛)にカスタマイズされた内容のメールが届きます。

※メールがどこから届くか等の設定は.envにて行う。今回は割愛。

ゆたんぽ

色んなやり方があるおかげでボクみたいな初心者には分かりづらい

ぬこ先生

使いこなせるときっと色んなものを作れる二ャ

 3:「リセットのビュー」からの挙動をカスタマイズ

届いたメールに添付されているリンクをクリックするとリセットのビューに飛びます。

そこで新しいパスワードを入力してバリデーション等を経て、問題なく更新されたらマイページへ。トークンの有効期限が切れてたりする場合は「トークエラーのビュー」にリダイレクトさせます。

そのへんのカスタマイズをしているのが↓のリセットコントローラーです。

ResetPasswordController.php

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
class ResetPasswordController extends Controller
{
    use ResetsPasswords;
    protected $redirectTo = '/mypage';
    public function reset(Request $request)
    {
         // バリデーション
        $request->validate([
            'token' => 'required',
            'email' => 'required|email',
            'password' => 'required|confirmed|min:8',
        ]);
    
        // パスワードリセットのロジックを実行
        $response = $this->broker()->reset(
            $this->credentials($request),
            function ($user, $password) {
                $this->resetPassword($user, $password);
            }
        );
    
        // トークンが期限切れているかどうかを確認
        if ($response === Password::PASSWORD_RESET) {
            // パスワードが正常にリセットされた場合のリダイレクト
            return redirect('/mypage')->with('flash_message', 'パスワードを変更しました');
        } else {
            // トークンが期限切れている場合のリダイレクト
            return redirect('/reset-link-expired')->with('flash_message', 'リンクの有効期限が切れています');
        }
    }
    
}

こんな感じで上記のマイページに飛ぶ(正常終了パターン)のは実現可能です。

あとはトークンエラーのビューを表示するためのルートを作ります。

【 web.php(など) 】

Route::get('/reset-link-expired', function () {
    return view('auth.passwords.reset_expired');
});

ここはお好みですが、今回はトークンエラーのビューを表示するだけのルーティングを設定することに。

以上で「パスワードリセット」の処理の一連のカスタマイズが完了しました!

まとめ

デフォルトでパスワードリセット機能がついており、非常に便利ではありますが、カスタマイズしたいとなるとやや面倒。。

パスワードリセットの流れ

① /resources/views/passwords/email.blade.php からメールアドレスを送信

② ForgotPasswordController.php で①の処理を行い、メールを送信

③ 送信されるメールを、カスタマイズしたものを使いたい場合

 ● メールの内容をカスタマイズしたテンプレートを用意

 ● Userモデルに、それを送信する設定を追記

④ カスタムされたメールに添付されているリンク(トークンが必要)をクリックすると、 /resources/views/passwords/reset.blade.php が表示される。

⑤ パスワードの更新、その後の挙動等は、 ResetPasswordController.php で行われる

⑥ トークンの有効期限が切れてたり。というエラー用のページを用意する場合は自作。(デフォルトではエラーメッセージだけ出るよう。)

という感じになっているようです。。

備忘録として自分用に残してはいますが、Laravelに慣れていない方の手助けになれば幸いです〜!

【Laravel5.8】パスワードリセットのカスタマイズ(備忘録:完全版)” に対して1件のコメントがあります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です