引き続きLaravel5.4での標準機能を利用した認証機能の実装を行います。
今回は本連載の最後としてパスワード初期化機能の実装を行います。
なお動作サンプルはコチラにありますので参考にして下さい。
また、本連載で作成または編集したファイルは(ほぼ)コチラに掲載しております。
目次
パスワード初期化機能の実装
早速パスワード初期化機能の実装を行います。
パスワード初期化URLリクエストフォームの準備
パスワード初期化URLリクエストフォーム用のビューを作成します。
以下の内容のファイルを「resources/views/user」配下に「password」フォルダを作成し、その中に「request.blade.php」として作成します。
パスワード初期化URLリクエストフォームの表示
さて、この状態で表示すると「View [auth.passwords.email] not found.」というエラーが発生しますので、新規利用登録フォームの表示時と同様に参照されているリソースを変更します。
作成したリソースを利用する場合、「app/Http/Controllers/User/ForgotPasswordController.php」にて「showLinkRequestForm」を次の内容でオーバライドして変更します。
エラーメッセージの修正
さて、エラーメッセージも新規利用登録フォームの表示時と同様に要素名がそのまま表示されていますので修正します。
「app/Http/Controllers/User/ForgotPasswordController.php」にて「validateEmail」を次の内容でオーバーライドします。
また、Requestクラスの利用に関する設定も同様に、以下の様にUSE演算子を使いインポートします。
メール送信メッセージの準備
標準の実装ではパスワード初期化URLリクエストを行った後は、元画面上にメールを送信した旨アラート表示が行われる動きとなっています。
しかし今回はメール送信後に送信完了のメッセージを表示するよう変更してみます。
まずは以下の内容のファイルを「resources/views/user/password」配下に「sent.blade.php」として作成します。
メール送信メッセージの表示
メール送信メッセージが表示されるよう処理を記述します。
「app/Http/Controllers/User/ForgotPasswordController.php」にて「sendResetLinkResponse」を次の内容でオーバーライドします。
メール送信処理の修正
さて、この状態で「パスワード初期化URLをリクエスト」ボタンをクリックするとどうなるでしょうか。
答えは「Route [password.reset] not defined.」とエラーが表示されます。
これはメール送信処理が実行された際、その中にパスワード初期化用URLを生成する部分で「password.reset」のルートを参照している為です。
ここではこのルートの修正と合わせて、送信メール自体も任意のテンプレートで送信できるように修正します。
メール送信処理を修正するにはNotificationクラスを継承した新たなクラスを作成し行いますので、以下のコマンドでファイルを作成します。
php artisan make:notification User/ResetPassword
上記のコマンドを実行すると「app/Notifications/User」配下に「ResetPassword.php」が作成されます。
実際に送信するメールを組み立てているのは「toMail」ですので、この部分を以下のように修正します。
ここでは件名(subject)の設定、送信元メールアドレス(from)の設定、そして実際に送信されるメールの本文に「user.emails.password」テンプレートを使用する設定を行っています。
また、「user.emails.password」テンプレート内で「restUrl」を利用している為、その変数に必要な情報を引き渡しています。
「restUrl」はリセット用のURLですので、URLを組み立ててその文字列を引き渡しています。
なお、その中で「$this->token」を参照しています。
これは標準機能で生成されたトークンをそのまま利用します。
トークン自体は呼び出し元で引き渡しを行いますが、ここでは受け取る処理を実装する必要があります。
その為、まずはクラス変数として「$token」を定義します。
次に、コンストラクタで引き渡されたトークンをクラス変数「$token」に代入する処理を記述します。
これでトークンをメールに埋め込む事ができます。
メール送信処理の差替え
さて、実際のメール送信処理の呼び出しを新たに作成したものに差し替える必要があります。
この差替えはUserモデルで行います。
以下の内容を「app/User.php」に追記します。
また、この処理が定義されたクラスも以下のようにUSE演算子を使いインポートします。
これで、メールの送信処理が新たに作成したものに差し替わりました。
メールテンプレートの作成
最後に実際に送信されるメールのテンプレートファイルを作成します。
「resources/views/user」配下に「mails」フォルダを作成し、その中に「password.blade.php」を以下の内容で作成します。
パスワード初期化リクエストフォームの準備
メールに記載されたパスワード初期化URLをクリックし表示されるパスワード初期化リクエストフォームを準備します。
以下の内容のファイルを「resources/views/user/password」配下に「reset.blade.php」として作成します。
パスワード初期化リクエストフォームの表示
パスワード初期化リクエストフォームが表示されるよう処理を記述します。
「app/Http/Controllers/User/ResetPasswordController.php」にて「showResetForm」を次の内容でオーバーライドします。
また、Requestクラスの利用に関する設定も同様に、以下の様にUSE演算子を使いインポートします。
エラーメッセージの修正
エラーメッセージで要素名がそのまま表示されている点も修正します。
これまでの用にバリデーション処理の部分でサクッと差替えできればよいのですが、残念ながらパスワードの初期化リクエストを処理する部分の実装を見てみるとバリデーションルールとメッセージのみの差し替えをそれぞれ個別に行う方法しか準備されていません。
いろいろ方法はありますが、最も単純な方法としてはここでも既存のトレイトへのリクエストに対して前処理としてバリデーションを行ってしまう方法です。
バリデーションルールが同じである限り、前処理で事前に検査を実行したとしてもその後に行われる検査結果への影響はありませんからね。
まずはトレイトの「reset」メソッドに別名を設定します。
次に「reset」メソッドをオーバーライドしてます。
幸いな事に既存の実装ではバリデーションルールを取得するためには「rules」、メッセージを取得するには「validationErrorMessages」という処理が実装済みですので、これらを使う事で影響は無さそうです。
これらで取得した結果を基に事前にバリデーションを実行します。
その後、改めて既存のトレイト上の「reset」メソッドを実行する事で、バリデーション以外の処理が実行される事となります。
初期化完了メッセージの準備
さて、標準機能ではパスワードの初期化が完了した後はホーム画面へリダイレクトされます。
これでも良いのですが、ここではパスワードが初期化された事を専用のメッセージを表示して通知したいと思います。
以下の内容のファイルを「resources/views/user/password」配下に「successful.blade.php」として作成します。
初期化完了時のリダイレクト先の変更
標準機能ではパスワードの初期化が完了した後はホーム画面へリダイレクトされますので、初期化完了メッセージを表示するパスへリダイレクトされるように修正します。
リダイレクト先は「ResetPasswordController.php」内の「$redirectTo」にて設定します。
初期化完了フラグのセット
さて、準備した初期化完了メッセージが表示されるよう処理を実装しますが、ここで一つ考える必要があります。
単純にGETメソッドで呼び出された際に表示すると、実際には初期化が完了していないのに表示され誤認される恐れもあります。
そこで、初期化処理が完了した時以外は初期化完了メッセージを表示しないように予め配慮しておく必要があります。
一番単純な方法としては正しく初期化完了された場合にフラグをセットし、そのフラグが有効な場合のみ初期化完了メッセージを表示する方法です。
初期化が正常に完了した場合、トレイトの「sendResetResponse」が呼び出されます。
この処理では「$redirectTo」にセットされたパスにフラッシュデータとして「status」をセットしリダイレクトを行っています。
この処理で合わせてフラグをセットすれば解決できそうです。
ここでは新たにフラッシュデータとして「reset」に「true」をセットし、それをフラグとして利用したいと思います。
具体的な実装は「app/Http/Controllers/User/ResetPasswordController.php」にて「sendResetResponse」を次の内容でオーバーライドします。
これで、フラッシュデータ内にフラグを準備する事ができました。
初期化完了メッセージの表示
それでは初期化完了メッセージが表示されるよう処理を記述します。
まずは、「app/Http/Controllers/User/ResetPasswordController.php」にて「showSuccessful」を次の内容で実装します。
処理の中身としては、先ほど準備した「reset」フラグを確認し、「true」がセットされている事を確認しています。
もしも「true」がセットされていない場合は、500エラーを発生させています。
フラッシュメッセージは直後のHTTPリクエストの間だけセッションにデータが保存されますので、一度初期化完了メッセージを表示したあと、仮にもう一度「/user/password/successful」を参照された場合であっても、500エラーが発生し、正しくハンドリングする事が可能です。
以上で標準の認証機能を利用して、新規利用者登録、ログインおよびログアウト、未ログイン状態や要ログインページでの例外処理、パスワード初期化など必要と思われる機能を一式実装してみました。
Laravelでは非常に簡単に認証機能を利用できるだけでなく、そのカスタマイズを比較的直感的に行えますので是非いろいろ試してみては如何でしょうか。