Laravel 5.7 のEmail Verification(本登録メール)の使い方

さてさて、このブログで何度も取り上げている人気PHPフレームワークのLaravelですが、新バージョン5.7が2018年9月4日に公開されました。

このマイナーバージョンアップによっていくつか新機能が追加されているわけですが、今回はその中でも特に便利だと感じた機能Email Verificationの使い方をまとめたいと思います。

ぜひ参考にしてみてください。

Email Verificationとは?

まずは機能の説明から。(知ってる方は次まで読み飛ばしてください)

例えば、あるウェブサイトを作って会員登録ができるようにするとします。この場合、いろいろなパターンのユーザー登録の方法がありますが、一般的によく使われるのは以下のような一旦Eメールを挟むパターンだと思います。

  1. メールアドレスとパスワード(+α)を入力してもらう
  2. 入力されたメールアドレスに仮登録のメールを送信
  3. 仮登録に書かれたURLにアクセスすると本登録が完了する

なぜこのパターンを使うかというと、

  • 入力されたメールアドレスが正しいことが確定する
  • 迷惑メール扱いされていたら解除してもらえる

といったメリットがあるからですね。

そして、Email Verificationはこの本登録用のメールのことを指しています。

では次からは実際にEmail Verificationを実装してみましょう!

Email Verificationの使い方

ユーザー登録できるようにする

Laravelは、ユーザー管理に関する以下の機能が始めから備わっています。

  • ユーザー登録
  • ログイン機能
  • パスワード・リマインダー(パスワードを忘れたとき用)

ただし、これらの機能はインストールしただけでは使うことはできません。
そのため、まずは以下のコマンドでDB、モデル、ビューなどを準備しましょう。

php artisan make:auth

次に、作成されたマイグレーション(DBテーブルの設計図)を以下のコマンドで実行して、テーブルを作成します。

php artisan migrate

以下が作成されたテーブルです。(ちなみに、Laravelはこの中のemail_verified_atフィールドを使って本登録 or 仮登録を判別します)

すると、トップページには

  • LOGIN ・・・ ログイン
  • REGISTER ・・・ 会員登録

のリンクが表示されるようになりました。

これでユーザー管理機能の準備は完了です。

※ここまではLaravel 5.6までの作業と同じです。

Email Verification機能を使えるようにする

MustVerifyEmailを追加する

ユーザー管理機能の準備は完了しましたが、まだこのままではEmail Verificationを使うことはできませんので、ここからがメインの作業になります。

まず、app/User.phpを開くと以下のようになっています。

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

そして、Email Verificationを使うためにMustVerifyEmailというインターフェイスを追加しましょう。

class User extends Authenticatable implements MustVerifyEmail
{
    // 省略
}

ちなみに、MustVerifyEmail用のネームスペースは始めから記述されている(こういうところがLaravel作者の気遣いできるところですね!)ので、implements MustVerifyEmailを追加するだけでOKです。

Routeの記述を変更する

では、次にRouteを変更します。routes/web.phpを開いてください。

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

この中にAuth::routes();と書かれた部分がありますが、これを以下のように変更します。

Auth::routes(['verify' => true]);

そして、verifiedという名前のミドルウェア使って「本登録したユーザーだけが表示できるページ」を登録しておきます。

Route::middleware('verified')->group(function() {

    // 本登録ユーザーだけ表示できるページ
    Route::get('verified',  function(){

        return '本登録が完了してます!';

    });

});

つまり、https://sample.test/verifiedは本登録しないと表示できません。

メール送信設定(必要な人だけ)

Laravelでメール送信をするためには.env内にあるMAIL_DRIVERを変更する必要があります。

MAIL_DRIVER=smtp

↓↓↓

MAIL_DRIVER=mail

※ご自身の環境に合わせて変更してください。もしわからない場合はlogとしておけば、メールを送信する代わりに、ログファイルに内容を保存してくれます。(私のローカル環境ではmailcatcherを使っているので、smtpで実行します)

実際に登録してみる

必要なデータを送信

では、ここから実際に登録してみます。

https://sample.test/register

へアクセスします。

必要な内容を入力して「Register」ボタンをクリックします。

仮登録が完了してログインできました。

本登録メッセージを確認

では、本登録用のメールが送信されているかチェックしてみましょう。


うまく送信されています。

では、ここで本登録ユーザーだけがアクセスできる、https://sample.test/verifiedへアクセスしてみましょう。

内容を要約すると、

「メールアドレスの認証をお願いします。もしメールを受け取ってないなら、ここをクリックしてください」

となります。

メールアドレスを認証する

先ほどのメールにあったVerify Email Addressボタンをクリックして本登録を完了させましょう。クリックするとログイン完了ページが表示されます。

では、最後になりました。

もう一度、https://sample.test/verifiedへアクセスしてみます。

web.phpに記述したテキストが表示されました!

これでEmail Verificationの実装は完了です。

お疲れ様でした。

 

日本語化

ここからはEmail Verificationの日本語化を説明します。

ちなみに、今回説明した、

  • ログインページ
  • ユーザー登録ページ
  • パスワード・リマインダーページ

の日本語化ついては、【Laravel5.6】インストール直後にやること3点で紹介しているのでそちらを参考にしてみてください。

本登録を促すページ

先ほど仮登録時に確認した以下のページを日本語化します。

ファイルは、resources/views/auth/verify.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">本登録</div>

                <div class="card-body">
                    @if (session('resent'))
                        <div class="alert alert-success" role="alert">
                            新しい本登録メッセージが送信されました。
                        </div>
                    @endif

                    メールアドレスの認証をお願いします。<br>
                    もしメールを受け取ってないなら、<a href="{{ route('verification.resend') }}">ここをクリックしてください</a>。
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

変更後リロードすると以下のようになります。

再送信リンクをクリックした場合。

本登録メール

まず以下のコマンドで専用のNotificationを作ります。

php artisan make:notification VerifyEmailJapanese

そして、app/Notifications内に作成したファイルがあるので開いて内容を以下のものに変更します。

<?php

namespace App\Notifications;

use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Lang;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;

class VerifyEmailJapanese extends Notification
{
    /**
     * The callback that should be used to build the mail message.
     *
     * @var \Closure|null
     */
    public static $toMailCallback;

    /**
     * Get the notification's channels.
     *
     * @param  mixed  $notifiable
     * @return array|string
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Build the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        if (static::$toMailCallback) {
            return call_user_func(static::$toMailCallback, $notifiable);
        }

        return (new MailMessage)
            ->subject(Lang::getFromJson('本登録メール'))
            ->line(Lang::getFromJson('以下の認証リンクをクリックして本登録を完了させてください。'))
            ->action(
                Lang::getFromJson('メールアドレスを認証する'),
                $this->verificationUrl($notifiable)
            )
            ->line(Lang::getFromJson('もしこのメールに覚えが無い場合は破棄してください。'));
    }

    /**
     * Get the verification URL for the given notifiable.
     *
     * @param  mixed  $notifiable
     * @return string
     */
    protected function verificationUrl($notifiable)
    {
        return URL::temporarySignedRoute(
            'verification.verify', Carbon::now()->addMinutes(60), ['id' => $notifiable->getKey()]
        );
    }

    /**
     * Set a callback that should be used when building the notification mail message.
     *
     * @param  \Closure  $callback
     * @return void
     */
    public static function toMailUsing($callback)
    {
        static::$toMailCallback = $callback;
    }
}

では、VerifyEmailJapaneseで本登録メールが送信されるようにapp/User.phpへ以下の内容を追加しましょう。

// Override
public function sendEmailVerificationNotification()
{
    $this->notify(new \App\Notifications\VerifyEmailJapanese);
}

※説明のために\App\Notifications\VerifyEmailJapaneseと書いてありますが、ネームスペースを使うことをおすすめします。

そして、これで本登録を送信してみると以下のようになります。

※ 上の画像を見ていただくとまだ英語部分が残っていますが、これはNotificationの方で変更をする必要があり、その方法は【Laravel5.6】インストール直後にやること3点で紹介しているので、そちらをご覧ください。

おわりに

今回のアップデートでは過去にあったような大きな機能追加はなかったようですが、このEmail Verificationはきっと重宝する機能になるのではないでしょうか。

ただ一点感じたのは、文化の違いからか「仮登録」が日本サイトでよく見る「まだログインできない登録」ではなく、ログインはできるが、何かをするには本登録が必要、という海外サイトでよくみるパターンとなっている点です。(当然と言えば当然ですけどね ^^;)

なので、もし日本向け仮登録を実装するには、少し工夫が必要かもしれません。ぜひ今後はその辺も探ってみたいと思います。

なにはともあれ、Laravel 5.7リリースおめでとうございます!



にほんブログ村 IT技術ブログへ  にほんブログ村 IT技術ブログ プログラム・プログラマーへ


BugGUI バグ報告を効率化
たった3分でバグ報告完了!? BugGUI