web-dev-qa-db-ja.com

Laravelリスナーは複数のイベントをリッスンします

したがって、laravel event doc によると、リスナーを定義するときに、handleメソッドでイベントインスタンスを受信し、必要なロジックを実行できます。

public function handle(FoodWasPurchased $event)

したがって、私のFoodWasPurchasedイベントが次のように定義されている場合(EventServiceProviderが設定されていると仮定):

public function __construct(Food $food)
{
    $this->food = $food;
}

次のようにして、リスナーからイベントの$ foodにアクセスできます。

$event->food->doSomething();

しかし、私の質問は、リスナーが複数のイベントを聞く場合はどうなるのでしょうか。

Event FoodWasPurchased -> Listener Bill
Event DrinksWasPurchased -> Listener Bill

私が今行ったことは、リスナーハンドルメソッドでイベントインスタンスを指定しなかったことです。

public function handle($event)

ここで、後でif条件を使用して、$ eventで受信されたものを確認できます。

if (isset($event->food)) {

    // Do something...

} elseif (isset($event->drinks)) {

    // Do something else...

}

もっと良い方法があると確信しています。

または、ベストプラクティスは、1人のリスナーが1つのイベントのみをリッスンするようにすることです。

14
Park Lai

Event Subscribers を使用して複数のイベントをリッスンできます。これは、Listenersフォルダーに配置されますが、複数のイベントをリッスンできます。

<?php

namespace App\Listeners;

class UserEventListener{
    /**
     * Handle user login events.
     */
    public function onUserLogin($event) {}

    /**
     * Handle user logout events.
     */
    public function onUserLogout($event) {}

    /**
     * Register the listeners for the subscriber.
     *
     * @param  Illuminate\Events\Dispatcher  $events
     * @return array
     */
    public function subscribe($events){
        $events->listen(
            'App\Events\UserLoggedIn',
            'App\Listeners\UserEventListener@onUserLogin'
        );

        $events->listen(
            'App\Events\UserLoggedOut',
            'App\Listeners\UserEventListener@onUserLogout'
        );
    }

}
20
jagzviruz

イベントがコントラクトまたはインターフェースに準拠している場合は、リスナーに好きなだけ渡すことができるようです...

class MyEventOne extends Event implements MyEventInterface

次に、EventServiceProviderでイベントとリスナーを接続します...

protected $listen = [
    'App\Events\MyEventOne' => [
        'App\Listeners\MyListener',
    ],
    'App\Events\MyEventTwo' => [
        'App\Listeners\MyListener',
    ],
];

そして最後に、リスナーで、コントラクト/インターフェースに基づいてイベントオブジェクトを受け入れるようにハンドラーにヒントを入力します...

public function handle(MyEventInterface $event)

私はこれをユニットテストしました。すべてのシナリオに適しているとは限りませんが、機能しているようです。お役に立てば幸いです。

8
RobDW1984

次のようなものも試すことができます。

// Instead of Food or Drink use parent Type
use Illuminate\Database\Eloquent\Model;

class DrinWasPurchased extends Event
{
    // Instead of Food or Drink typehint Model        
    public function __construct(Model $model)
    {
        // Instead of $this->food or $this->drink use a generic name
        $this->item = $model;
    }
}

次に、リスナーのhandleメソッドで、次のようにします。

public function handle(\App\Events\Event $event)
{
    if($event->item instanceof \App\Food)
    {
        $item->eat(); // Just an example
    }

    if($event->item instanceof \App\Drink)
    {
        $item->drink(); // Just an example
    }
}
6
The Alpha

1- EventServiceProviderに追加します:

'App\Events\NewMessageSent' => [
    'App\Listeners\SendNewMessageNotificationToRecipients',
],
'App\Events\MessageReplied' => [
    'App\Listeners\SendNewMessageNotificationToRecipients',
],
'App\Events\MessageForwarded' => [
    'App\Listeners\SendNewMessageNotificationToRecipients',
],

2-イベントとリスナーを生成します。

php artisan event:generate

3- SendNewMessageNotificationToRecipients.php(リスナー)の場合:

use App\Events\Event;
use App\Events\NewMessageSent;
use App\Events\MessageReplied;
use App\Events\MessageForwarded;

public function handle(Event $event)
{
    if ($event instanceof NewMessageSent) {
        dd('message sent');
    } else if ($event instanceof MessageReplied) {
        dd('message replied');
    } else if ($event instanceof MessageForwarded) {
       dd('message forwarded');
    }
}
2
jvicab