2015-07-10 321 views
8

所以根据laravel事件doc,定义监听器时,它可以在自己的处理方法接收事件实例,并进行必要的逻辑:Laravel监听器监听多个事件

public function handle(FoodWasPurchased $event) 

所以,如果我的FoodWasPurchased事件被定义为如下(设为EventServiceProvider设置):

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

我能从听众通过做访问$食品事件荷兰国际集团:

$event->food->doSomething(); 

但现在我的问题是,如果有什么监听器监听多个事件?

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

我现在做的是我没有在听者处理方法指定事件实例:

public function handle($event) 

,我可以在以后使用的,如果条件检查什么在$活动得到:

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

    // Do something... 

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

    // Do something else... 

} 

我确定有更好的办法。

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

回答

12

您可以收听多个事件:

// 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方法尝试这样的事情放置在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\[email protected]' 
     ); 

     $events->listen(
      'App\Events\UserLoggedOut', 
      'App\Listeners\[email protected]' 
     ); 
    } 

} 
+0

我们如何从控制器调用这个类? –

+0

EventListeners在引发相应事件时触发。所以你必须在控制器内触发事件。 – jagzviruz

4

你可以尝试这样的事情还有:使用Event Subscribers这是

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 
    } 
} 
+0

此做增加可读性。但是如果一个听众收听2个以上的事件呢? (或者,最好的办法是确保所有事件都通过相同类型的实例?) –

+0

如果使用PHPStorm,可以省略'$ event'的类型提示并使用@param doc。 – Kyslik

4

如果您的活动符合合同或接口似乎你可以尽可能多的传递,你喜欢给听众......

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) 

我已经进行单元测试这一点,可能不适合所有情况,但它似乎工作。我希望它有帮助。

0

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