Laravel 监听器监听多个事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31345686/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:55:27  来源:igfitidea点击:

Laravel listener listen to multiple event

eventslaravellaravel-5

提问by Park Lai

So according to the laravel event doc, when defining listeners, it can receive the event instance in their handle method and perform any logic necessary:

因此,根据 laravel event doc,在定义侦听器时,它可以在其 handle 方法中接收事件实例并执行任何必要的逻辑:

public function handle(FoodWasPurchased $event)

So if my FoodWasPurchasedevent is defined as below (assumed EventServiceProvider is set):

因此,如果我的FoodWasPurchased事件定义如下(假设设置了 EventServiceProvider):

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

I could access the $foodin event from listener by doing:

我可以通过执行以下操作从侦听器访问事件中的$food

$event->food->doSomething();

But now my question is what if a listener listen to multiple events?

但现在我的问题是,如果一个听众监听多个事件呢?

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

What I did now is I did not specify the event instance in the listener handle method:

我现在所做的是我没有在侦听器句柄方法中指定事件实例:

public function handle($event)

where I can later use an if condition to check what is received in the $event:

稍后我可以使用 if 条件来检查 $event 中收到的内容:

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

    // Do something...

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

    // Do something else...

}

I'm sure there is a better way.

我相信有更好的方法。

Or the best practice is ensure that one listener only listens to one single event ?

或者最好的做法是确保一个听众只听一个事件?

回答by jagzviruz

You can listen to multiple events by using Event Subscriberswhich are placed in the Listeners folder but are capable of listening to multiple events.

您可以使用放置在 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'
        );
    }

}

回答by RobDW1984

If your events conform to a contract or interface it seems you can pass as many as you like to a listener...

如果您的事件符合合同或接口,那么您似乎可以将任意数量的事件传递给侦听器...

class MyEventOne extends Event implements MyEventInterface

Then in the EventServiceProvider you connect up your events and listeners as so...

然后在 EventServiceProvider 中,您将事件和侦听器连接起来……

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

And finally in your listener you type hint your handler to accept the event object based on the contract/interface...

最后在您的侦听器中键入提示处理程序以接受基于合同/接口的事件对象...

public function handle(MyEventInterface $event)

I've unit tested this, it may not be appropriate for every scenario, but it seems to work. I hope it helps.

我已经对此进行了单元测试,它可能不适用于所有场景,但它似乎有效。我希望它有帮助。

回答by The Alpha

You may try something like this as well:

你也可以尝试这样的事情:

// 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;
    }
}

Then in the handlemethod of listener try something like this:

然后在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
    }
}

回答by jvicab

1- Add to EventServiceProvider:

1- 添加到 EventServiceProvider:

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

2- Generate events and listener:

2- 生成事件和监听器:

php artisan event:generate

3- On SendNewMessageNotificationToRecipients.php (listener):

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');
    }
}