こんにちは、aiiro(@aiiro29)です。
Laravel5.7に新機能、ユーザーのメールアドレス確認機能が追加されました!
今回はLaravel5.7で追加された、ユーザー登録をした時に入力したメールアドレスを確認する機能(Email Verification)を紹介します。

アプリケーションを開発していると、メールアドレスの確認がまだ済んでいないユーザーに対して、確認を促すようにメッセージを表示したいということがあります。
メールアドレスの確認機能Laravelでサポートされるようになったことで、自分たちで実装しなければならない処理を減らせそうです。
Laraveの使い勝手が一層向上することが期待できますね。
アプリケーションの開発を安全かつ楽にするためにも、Laravel5.7を使い始める前に、メールの確認機能の使い方と、その仕組みについて確認しておきたいと思います。
使い方
Userモデルに MustVerifyEmail を追加する
App\User
モデルで Illuminate\Contracts\Auth\MustVerifyEmail
インターフェースを実装します。
use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmail;
// (中略)
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
// ...
}
make:auth コマンドを実行する
make:authコマンドを実行して、認証関連のファイルを生成します。
メールアドレスが確認できていないユーザー向けに表示する画面のテンプレートも生成されます。
テンプレートは resources/views/auth/verify.blade.php
に作成されます。
php artisan make:auth
ルーティングを設定する
web.php
に Auth::routes(['verify' => true]);
を設定します。
更に middleware('verified')
を使用して、メールアドレスが確認済みの場合のみアクセスできるようにしたいルーティングを設定します。
Route::get('/', function () {
return view('welcome');
})->middleware('verified');
Auth::routes(['verify' => true]);
Route::get('/home', 'HomeController@index')->name('home');
以上で準備は完了です。
動作確認
ユーザー登録をしたときに、usersテーブルに email_verified_at
がnullのレコードが登録されていることを確認します。
メールアドレスが確認されていないままで verified
ミドルウェアを設定したエンドポイントにアクセスすると、email/verify
にリダイレクトされます。
このとき表示されているテンプレートが、 resources/views/auth/verify.blade.php
です。
入力したメールアドレスにメールが送信されていますので、メール中のリンクをクリックします。
成功すると email_verified_at
が更新されます。
メールアドレスの確認後は、ミドルウェアで制限しているエンドポイントにアクセスできるようになります。
メール確認機能の仕組み
使い方は以上ですが、Email Verificationがどういう仕組で動いているかを見ておきたいと思います。
MustVerifyEmailについて
App\Http\Kernel
で $routeMiddleware
に設定があるので、そこから確認します。
class Kernel extends HttpKernel
{
// 中略
protected $routeMiddleware = [
// 中略
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
Illuminate\Auth\Middleware\EnsureEmailIsVerified
が使用されていることがわかりました。
それでは Illuminate\Auth\Middleware\EnsureEmailIsVerified
の実装を見てみます。
class EnsureEmailIsVerified
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response
*/
public function handle($request, Closure $next)
{
if (! $request->user() ||
($request->user() instanceof MustVerifyEmail &&
! $request->user()->hasVerifiedEmail())) {
return Redirect::route('verification.notice');
}
return $next($request);
}
}
EnsureEmailIsVerified
はhandle()で userが MustVerifyEmail
のインスタンスかどうかを判定し、
メールアドレスが未確認であればリダイレクトさせています。
“App\Userモデル”で”MustVefiryEmail”をimplementsしたのは、このためです。
また、上記のコードで使用されている”hasVerifiedEmail()”ですが、これは”Illuminate\Auth\MustVerifyEmail”トレイトで定義されています。
次は”Illuminate\Auth\MustVerifyEmail”トレイトをどうやって利用しているかを見ていきます。
Authenticatableについて
“Illuminate\Auth\MustVerifyEmail”トレイトをどうやって利用しているかを知るためには、”Illuminate\Foundation\Auth\User”を読むことになります。
理由は”Illuminate\Foundation\Auth\User”が”Illuminate\Foundation\Auth\User”は”Illuminate\Auth\MustVerifyEmail”トレイトを使用しているためです。
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements
AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
}
そして”App\User”モデルは”Illuminate\Foundation\Auth\User”に“Authenticatable”というエイリアスを設定し、継承しています。
<?php
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements MustVerifyEmail
{
// ...
}
“Illuminate\Foundation\Auth\User”はトレイトである”Illuminate\Auth\MustVerifyEmail”をuseしていますが、インターフェースである”Illuminate\Contracts\Auth\MustVerifyEmail”をimplementsしていません。
そのため、”App\Userモデル”でインターフェースを実装する必要があったのです。
登録されたメールアドレスにメールを送信する仕組み
ユーザー登録時に入力されたメールアドレスに、メールを送信する処理について、確認したいと思います。
config/app.php
でサービスプロバイダーとして App\Providers\EventServiceProvider::class
が登録されているので、中身を見てみましょう。
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
//
}
}
EventServiceProviderでは$listen
に SendEmailVerificationNotification
が設定されています。
SendEmailVerificationNotification
を読んでみると、 Illuminate\Auth\Listeners
配下のリスナーであることがわかります。
class SendEmailVerificationNotification
{
/**
* Handle the event.
*
* @param \Illuminate\Auth\Events\Registered $event
* @return void
*/
public function handle(Registered $event)
{
if ($event->user instanceof MustVerifyEmail) {
$event->user->sendEmailVerificationNotification();
}
}
}
SendEmailVerificationNotification
ではuserが MustVefiryEmail
のインスタンスかどうかを判定し、 sendEmailVerificationNotification()
を使ってNotificationを送信しています。
まとめ
Laravel5.7で追加されたメールアドレスの確認機能の使い方と仕組みについて紹介しました。
メールアドレスの検証機能は多くのアプリケーションで実装されている機能ですが、LaravelのEmail Verificationを使用することで、自分たちで実装するコードをグッと減らすことができるようになっています。
以上の内容が、メールアドレスの確認機能を使ってみようと思っている方にとって、参考になれば幸いです。