皆さんEvent使ってますか?
わしは最近初めて使いました😇
イベント・リスナを使うとOberverパターンの実装ができるので
処理が独立化し、Controller等がよりスッキリしますよ☺️
さて今回は、Laravel 5.8.9から実装された イベントディスカバリ を使う機会があったので
サクッと紹介してみたいと思います!
イベントディスカバリとは
Laravelでイベントを作成した場合は EventServiceProvider
や Subscriber
の中でイベント・リスナを登録する必要があります。
これを
「所定のディレクトリにイベントを置いておけば自動で登録しといてあげるよー!」
という親切機能がイベントディスカバリです。
詳細は公式ドキュメントの「イベントディスカバリ」項をご参照ください。
https://readouble.com/laravel/5.8/ja/events.html
何が嬉しいのか
イベント・リスナの登録作業は地味に面倒です。
もっとビジネスの本質に集中したい😤
また、サブスクライバを使う場合はイベント登録を忘れると「なぜか動かない」状態になってしまい、
原因追及に時間がかかってしまうことがあります(ありました)。
その点、イベントディスカバリは一度設定してしまえば、
イベント・リスナを所定のディレクトリに作成するだけで登録できるので、
面倒な作業やハマりから解放されますね☺️
使い方
EventServiceProvider
でshouldDiscoverEvents()
をオーバーライドします。
public function shouldDiscoverEvents()
{
// 親クラスでfalseになってるのをtrueで上書きする
return true;
}
これで、Listenersディレクトリに作成したリスナが自動で登録されます!🙌
以上
簡単ですねー!
[補足]何をやっているのか
シンプルでいいのですが記事としてあまりに寂しいのでもうちょっと調べてみました。
ソースを追っていくとメインの処理はこのあたりのようです
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);
}
ReflectionClass
やReflectionMethod
を使って
所定のディレクトリからListerのhandleメソッドを取得し、
$listenerEvents[リスナ@handle名] = イベントのクラス名
の形式にして返してます。
他のところでデータの加工などしていますが、最終的にはEventServiceProvider
(親クラスの方)で、
手動登録したイベント・リスナとガッチャンコで処理されるという仕組みのようです!
[補足]サブスクライバー使ってるとどうなるの?
結論から書くと、Subscrivberを使っていても問題なかったです!
今回元の実装がSubscriberのhandleの引数にイベントクラスのinterface
を取っていたけど、
これはこれで別に問題ないらしい。
class PiyoEventSubscriber implements ShouldQueue
{
public function subscribe(Dispatcher $dispatcher)
{
// 前はここで $dispatcher->listen() してイベント登録していた
}
// PiyoEventはinterface
// これを実装したイベントクラスがたくさんある
public function handle(PiyoEvent $event)
{
$event->send();
}
}
以上
指摘・補足などあればコメントいただけると嬉しいです!