【前篇】に続いて、今回もユーザー登録機能に確認メールの送信を追加するカズタマイズを進めます。
進捗確認
【前篇】では、基本的なユーザー登録、ログインを実装した後に、以下の2点をカスタマイズしました。
- ユーザー登録直後に確認メールを送信
- 確認メール内のURLにアクセスして、ユーザー確認を完了
【後編】では、以下の2点を追加します。
- 確認メールからのユーザー確認が済んでいない時、ログイン出来ないようにする。
- 確認メールの再送を可能にする。
ミドルウェアでフィルタリング
# ミドルウェアの作成
確認メールからのユーザー確認が済んでいるかどうかをチェックするミドルウェアを作成します。
php artisan make:middleware VerifyConfirmed
app/Http/Middleware/VerifyConfirmed.php が作成されるので、以下のように編集します。
<?php // app/Http/Middleware/VerifyConfirmed.php namespace App\Http\Middleware; use Closure; use App\User; class VerifyConfirmed { public function handle($request, Closure $next) { $user = User::where('email', '=', $request->input('email'))->first(); if ($user) { if(! $user->isConfirmed()) { \Session::flash('flash_message', 'ユーザー登録確認メールに従って、ユーザーを有効化してください。'); return redirect()->back()->withInput($request->only('email')); } } return $next($request); } }
handle() メソッドの中で、入力されたメールアドレスでユーザーを検索し、ユーザー登録確認済かどうかをチェックしています。確認済みでないなら、直前の画面にリダイレクトします。
# ミドルウェアを Laravelに登録
app/Http/Kernel.php を編集します。
<?php // app/Http/Kernel.php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { // ... protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'confirm' => \App\Http\Middleware\VerifyConfirmed::class, // ① 追加 ];}
① VerifyConfirmed を ‘confirm’ というキーで $routeMiddleware に登録します。
# ログイン処理でミドルウェアを使う
app/Http/Controllers/Auth/AuthController.php を編集します。
<?php // app/Http/Controllers/Auth/AuthController.php namespace App\Http\Controllers\Auth; class AuthController extends Controller { use AuthenticatesAndRegistersUsers; public function __construct() { $this->middleware('guest', ['except' => 'getLogout']); $this->middleware('confirm', ['only' => 'postLogin']); // ① 追加 } // ... }
① postLogin() メソッドにだけ、’confirm’ミドルウェアを実行するように、追加します。
これで、ログイン画面からログインした時に、確認メールからのユーザー確認が済んでいない場合は、ログイン出来ないようになりました。
確認メールの再送
# コントローラー
AuthController.php にアクションを追加します。
<?php // app/Http/Controllers/Auth/AuthController.php namespace App\Http\Controllers\Auth; // ... use App\User; use Illuminate\Contracts\Config\Repository as Config; class AuthController extends Controller { // ... /** * ① 確認メール再送画面を表示する * * @return \Illuminate\View\View */ public function getResend() { return view('auth.confirm'); } /** * ② 確認メールの再送信する * * @param Request $request * @return $this|\Illuminate\Http\RedirectResponse */ public function postResend(Request $request, Mailer $mailer, Config $config) { $this->validate($request, ['email' => 'required|email']); $user = User::where('email', '=', $request->input('email'))->first(); if(! $user) { return redirect()->back() ->withInput($request->only('email')) ->withErrors(['email' => trans('passwords.user')]); } if($user->isConfirmed()) { \Session::flash('flash_message', '既に、ユーザー登録が完了しています。ログインしてください。'); return redirect('auth/login'); } $this->sendConfirmMail($mailer, $user); \Session::flash('flash_message', 'ユーザー登録確認メールを送りました。'); return redirect()->guest('auth/login'); } }
① getResend() を追加し、確認メールの再送信画面を表示します。
② postResend() を追加し、入力されたメールアドレスに確認メールを再送信します。
# ルート
routes.phpにルートを追加します。
<?php // app/Http/routes.php ... // ユーザー登録 ... Route::get('auth/resend', 'Auth\AuthController@getResend'); Route::post('auth/resend', 'Auth\AuthController@postResend'); ...
artisanコマンドでルートを確認してみます。
php artisan route:list
+--------+----------+--------------------------+------------------+--------------------------------------------------------+------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+--------------------------+------------------+--------------------------------------------------------+------------+ | | GET|HEAD | auth/resend | | App\Http\Controllers\Auth\AuthController@getResend | guest | | | POST | auth/resend | | App\Http\Controllers\Auth\AuthController@postResend | guest | +--------+----------+--------------------------+------------------+--------------------------------------------------------+------------+
getResend()や postResend()へのルートが追加されました。
# ビュー
確認メールの再送信画面を作成します。
{{-- resources/views/auth/confirm.blade.php --}} @extends('layout') @section('content') <div class="container-fluid"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-heading">ユーザー登録確認メールの再送信</div> <div class="panel-body"> @if (count($errors) > 0) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form class="form-horizontal" role="form" method="POST" action="{{ url('/auth/resend') }}"> <input type="hidden" name="_token" value="{{ csrf_token() }}"> <div class="form-group"> <label class="col-md-4 control-label">E-Mail Address</label> <div class="col-md-6"> <input type="email" class="form-control" name="email" value="{{ old('email') }}"> </div> </div> <div class="form-group"> <div class="col-md-6 col-md-offset-4"> <button type="submit" class="btn btn-primary"> 再送信 </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection
ユーザー登録画面に、確認メールの再送画面へのリンクを追加します。
{{-- resources/views/auth/register.blade.php --}} @extends('layout') @section('content') <div class="container-fluid"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-heading">Register</div> <div class="panel-body"> // ... <form class="form-horizontal" role="form" method="POST" action="{{ url('/auth/register') }}"> // ... <div class="form-group"> <div class="col-md-6 col-md-offset-4"> {{-- 登録ボタン --}} <button type="submit" class="btn btn-primary"> Register </button> {{-- 確認メール再送画面へのリンクを追加 --}} <a class="btn btn-link" href="{{ url('/auth/resend') }}">ユーザー登録確認メールを再送する</a> </div> </div> </form> </div> </div> </div> </div> </div> @endsection
まとめ
ユーザー登録機能に確認メールの送信を追加するカスタマイズが完了しました。
動作確認をしてみてください。
- ユーザー登録直後に確認メールが送信される。
- 確認メール内のURLにアクセスすると、ユーザー確認を完了する。
- 確認メールからのユーザー確認が済んでいない時はログインできない。
- 確認メールの再送ができる。