2015-07-10 317 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'); 
    } 
}