LoginSignup
8
2

More than 3 years have passed since last update.

Laravelのイベントディスカバリを試してみる

Last updated at Posted at 2019-06-21

皆さんEvent使ってますか?
わしは最近初めて使いました😇
イベント・リスナを使うとOberverパターンの実装ができるので
処理が独立化し、Controller等がよりスッキリしますよ☺️

さて今回は、Laravel 5.8.9から実装された イベントディスカバリ を使う機会があったので
サクッと紹介してみたいと思います!

イベントディスカバリとは

Laravelでイベントを作成した場合は EventServiceProviderSubscriber の中でイベント・リスナを登録する必要があります。
これを
「所定のディレクトリにイベントを置いておけば自動で登録しといてあげるよー!」
という親切機能がイベントディスカバリです。

詳細は公式ドキュメントの「イベントディスカバリ」項をご参照ください。
https://readouble.com/laravel/5.8/ja/events.html

何が嬉しいのか

イベント・リスナの登録作業は地味に面倒です。
もっとビジネスの本質に集中したい😤

また、サブスクライバを使う場合はイベント登録を忘れると「なぜか動かない」状態になってしまい、
原因追及に時間がかかってしまうことがあります(ありました)。

その点、イベントディスカバリは一度設定してしまえば、
イベント・リスナを所定のディレクトリに作成するだけで登録できるので、
面倒な作業やハマりから解放されますね☺️

使い方

EventServiceProvidershouldDiscoverEvents()をオーバーライドします。

EventServiceProvider
public function shouldDiscoverEvents()
{
    // 親クラスでfalseになってるのをtrueで上書きする
    return true;
}

これで、Listenersディレクトリに作成したリスナが自動で登録されます!🙌

以上

簡単ですねー!

[補足]何をやっているのか

シンプルでいいのですが記事としてあまりに寂しいのでもうちょっと調べてみました。

ソースを追っていくとメインの処理はこのあたりのようです

DiscoverEvents.php
    protected static function getListenerEvents($listeners, $basePath)
    {
        $listenerEvents = [];

        foreach ($listeners as $listener) {
            $listener = new ReflectionClass(
                static::classFromFile($listener, $basePath)
            );

            foreach ($listener->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
                if (! Str::is('handle*', $method->name) ||
                    ! isset($method->getParameters()[0])) {
                    continue;
                }

                $listenerEvents[$listener->name.'@'.$method->name] =
                                optional($method->getParameters()[0]->getClass())->name;
            }
        }

        return array_filter($listenerEvents);
    }

ReflectionClassReflectionMethodを使って
所定のディレクトリからListerのhandleメソッドを取得し、
$listenerEvents[リスナ@handle名] = イベントのクラス名の形式にして返してます。

他のところでデータの加工などしていますが、最終的にはEventServiceProvider(親クラスの方)で、
手動登録したイベント・リスナとガッチャンコで処理されるという仕組みのようです!

[補足]サブスクライバー使ってるとどうなるの?

結論から書くと、Subscrivberを使っていても問題なかったです!
今回元の実装がSubscriberのhandleの引数にイベントクラスのinterfaceを取っていたけど、
これはこれで別に問題ないらしい。

PiyoEventSubscriber
class PiyoEventSubscriber implements ShouldQueue
{
    public function subscribe(Dispatcher $dispatcher)
    {
        // 前はここで $dispatcher->listen() してイベント登録していた
    }

    // PiyoEventはinterface
    // これを実装したイベントクラスがたくさんある
    public function handle(PiyoEvent $event)
    {
        $event->send();
    }
}

以上

指摘・補足などあればコメントいただけると嬉しいです!

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2