Laravelのイベント&リスナについてまとめてみた

こんにちは、 株式会社SCOUTERエンジニアの佐藤(@r_sato1201)です

今回は、Laravelのイベント機能についてまとめたいと思います。

Laravelのイベントとは?

ReaDouble(公式リファレンスサイトを和訳したサイト)には以下のように記述してあります。

Laravelのイベントはシンプルなオブザーバの実装で、アプリケーションで発生する様々なイベントを購読し、リッスンするために使用します

参考:Laravel5.7 イベント

Laravelのイベント機能はObserverパターンで実装されています。
Observerパターンとは、観察される側(Subject)と観察する側(Observer)の2つの役割が存在し、観察される側の状態が変化した際に、観察する側に通知されるデザインパターンです。
Laravelではイベント(観察される側)とリスナ(観察する側)とに分かれており、イベントの変化をリスナが補足することで処理を行うという流れになっているようです。

イベント、リスナの登録

ここからは、「アカウント登録した際に、ユーザーに登録完了メールを送信する」機能を例に説明したいと思います。
まずはイベントとリスナの登録です。Laravelでは基本的にEventServiceProviderで管理されているので、listenプロパティに以下のように記述します。

app/Providers/EventServiceProvider.php

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    // アカウント登録
    Events\RegisterAccount::class => [
        Listeners\SendRegisterAccountNotification::class,
    ],
];

イベント、リスナの作成

次は、イベントとリスナの作成です。

php artisan event:generate

上記のコマンドを実行することで、EventServiceProviderに記述してあるイベントやリスナを生成してくれます。なお、既に作成済みのものには、変更を加えません。
app配下にEventsディレクトリとListenersディレクトリが生成され、RegisterAccount.phpとSendRegisterAccountNotification.phpが生成されます。

イベント定義

次に、イベントの定義をしていきましょう。

app/Events/RegisterAccount.php

<?php

namespace App\Events;

use App\Entities\User;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;

class RegisterAccount
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * @var User
     */
    private $user;

    /**
     * Create a new event instance.
     *
     * @param User $user
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function getUser()
    {
        return $this->user;
    }
}

メンバ変数のuserを定義して、getUser()でいつでも取り出せるようにしています。

リスナ定義

次に、リスナの定義です。

app/Listeners/SendRegisterAccountNotification.php

<?php

namespace App\Listeners;

use App\Events\RegisterAccount;
use App\Notifications\RegisterAccountMailNotification;

class SendRegisterAccountNotification
{
    /**
     * Handle the event.
     *
     * @param  RegisterAccount $event
     *
     * @return void
     */
    public function handle(RegisterAccount $event)
    {
        $user = $event->getUser();
        $user->notify(new RegisterAccountMailNotification($user));
    }
}

ここでは、Eventでキャッチした$userを、ユーザーにメール送信するNotificationである RegisterAccountMailNotificationに渡しています。
※RegisterAccountMailNotificationの内容はここでは省きます。

ちなみに、app/Entities/User.phpで、Notifiableトレイトを定義しておかないとNotificationが動かないので注意してください。

class User extends BaseModel 
{
    use Notifiable {
        notify as traitNotify;
    }
}

イベント発行

最後に、これまで記述してきたイベント処理を発行させる処理を記述します。
app/Http/Controllers/Api/RegisterController.php

<?php

namespace App\Http\Controllers\Api\Company;

use App\Events\RegisterAccount;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class RegisterController extends Controller
{
    /**
     * Create a new user instance
     *
     * @param array $data
     *
     */
    protected function create(Request $request)
    {
        $user = ([
            'email' => $request['email'],
            'password' => $request['password'],
        ]);

        RegisterAccount::dispatch($user);
    }
}

先程作成したイベントファイル(RegisterAccount)をuseし、dispatchしています。 これで、ユーザーがアカウント登録をした際に、ユーザーに対してアカウント登録メールを送信することができるようになりました。

まとめ

以上で、「アカウント登録した際に、ユーザーに登録完了メールを送信する」機能を一通り実装することができました。

今後は、

・イベントリスナのキュー投入
・ブロードキャスト

などを学び、理解してアウトプットしていけたらと考えています。

さいごに

現在、株式会社SCOUTERでは、エンジニア、デザイナーの募集をしております。

興味のある方は、是非下記からご応募お願い致します!

www.wantedly.com

www.wantedly.com

www.wantedly.com

参考資料