Laravelで会員登録完了メールを送る方法[後編]

Laravelで登録完了メールを送る方法

こんにちはーむちょこです。

今日はLaravelのイベントとメール配信機能を使って、会員登録が完了したときにメールを送る方法の後編として、イベント機能部分についてご紹介していきます☆

まだ前編のメール配信機能部分をご覧になっていない方は、こちらをどうぞ!

Laravelで登録完了メールを送る方法 Laravelで会員登録完了メールを送る方法[前編]

5. イベント機能とは

“イベント”は、なにかしらの動作や変更のとこを指します。

イベント機能とは、Dispacherがイベントを発行し、Listenerがそれを受信して対応する処理を実行する機能です。

イベント機能

Laravelのイベント機能はObserverパターンで実装されています。

Observerパターン
Observerパターン

上記のObserverがListener、SubjectがEventとして当てはまります。

6. Listenerクラスの準備

Eventクラスは元々Laravelで用意されているクラスを使うので、今回はリスナのみを実装します。
まずはプロバイダに使いたいListenerクラスを登録しましょう。

app/Providers/EventServiceProvider.php
protected $listen = [
    'Illuminate\Auth\Events\Registered' => [
        'App\Listeners\RegisteredListener'
    ]
];

Listenerクラスを登録してから次のコマンドを実行すると、必要なクラスファイルを自動生成してくれます。

コマンド
$ php artisan event:generate

7. Listenerクラスの実装

生成されたクラスのうち、RegisteredListener.phpの方を編集していきます。

app/Listeners/RegisteredLisntener.php
use App\Mail\RegisteredMail;
use Illuminate\Support\Facades\Mail;

class RegisteredListener
{
    /**
     * Handle the event.
     *
     * @param  Registered  $event
     * @return void
     */
    public function handle(Registered $event)
    {
        $user = $event->user;
        Mail::to($user)
            ->send(new RegisteredMail($user));
     }
}

これで、Registeredイベントが発行されたときに前編で実装した登録完了メールが送信されるようになりました。

8. テスト

一連の流れがきちんと動作することを保証するためにテストを行います。

まずは以下のコマンドを実行して、テストクラスを生成してください。

コマンド
$ php artisan make:test AuthTest

unitオプションをつけなかったので、今回はtest/Featureディレクトリ下にファイルが生成されます。

tests/Feature/AuthTest.php
use Illuminate\Support\Facades\Event;
use Illuminate\Auth\Events\Registered;

class AuthTest extends TestCase
{
    /**
    *  会員登録のテスト
    *
    */
    public function testRegister()
    {
        Event::fake();

        //新規会員情報の送信
        $user = factory(\App\User::class)->make();
        $user = $user->toArray();
        $user['password'] = 'testtest';
        $user['password_confirmation'] = 'testtest';

        $response = $this->post('/register', $user);
 
        //homeページへのリダイレクトをアサート
        $response->assertRedirect('/home');

        //送信したユーザ情報がDBにあることをアサート
        $this->assertDatabaseHas('users', [
            'name' => $user['name'],
            'email' => $user['email']
        ]);

        //イベントがディスパッチされたことをアサート
        Event::assertDispatched(Registered::class, function ($event) use ($user) {
            return $event->user->email === $user['email'];
        });

        //イベントが1回だけディスパッチされたことをアサート
        Event::assertDispatched(Registered::class, 1);
    }
}

中身を分解してお話していきます。

use Illuminate\Support\Facades\Event;
Event::fake();

前回はMailファサードのfakeメソッドを使いました。

今回はそれのEventファサードver.で、同様に「イベントが起こったことにする(実際には起こらない)」ためのメソッドです。テストを実行する度にイベント処理が行われるのを防ぎます。

        $user = factory(\App\User::class)->make();
        $user = $user->toArray();
        $user['password'] = 'testtest';
        $user['password_confirmation'] = 'testtest';

仮のユーザモデルを生成するのは前回と同じですが、そのままだとパスワードのデータが使えないので配列に変換してパスワード部分だけべた書きしています。

$response = $this->post('/register', $user);

見たままですが、/registerに$user配列をPOST送信しています。
ちなみに第二引数は配列でなければいけないので、仮にパスワード云々がなくてもUserオブジェクトは配列に変換しておく必要があります。

//homeページへのリダイレクトをアサート
$response->assertRedirect('/home');

/homeは、RegisterControllerクラスの$redirectToの値です。

//送信したユーザ情報がDBにあることをアサート
$this->assertDatabaseHas('users', [
    'name' => $user['name'],
    'email' => $user['email']
]);

以下のようなSQL文が実行され、データが存在すればtrueになります。
select count(*) as aggregate from users where (name = $user[‘name’] and email = $user[‘email’])

use Illuminate\Auth\Events\Registered;

//イベントがディスパッチされたことをアサート
Event::assertDispatched(Registered::class, function ($event) use ($user) {
    return $event->user->email === $user['email'];
});

イベントクラスは元々Laravelに用意されているIlluminate\Auth\Events\Registeredを使用していますので、ディスパッチのアサートにもそのRegisteredクラスを指定します。

それではテストを実行します。

コマンド
$ ./vendor/bin/phpunit tests/Feature/AuthTest.php

テスト結果がOKになれば完了です!

実際にブラウザから会員登録を行うと、このようなメールが送信されます。

1 Comment

現在コメントは受け付けておりません。