国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

事件系統(tǒng)

事件系統(tǒng)


事件系統(tǒng)

事件系統(tǒng)介紹

Laravel 的事件提供了一個(gè)簡(jiǎn)單的觀察者實(shí)現(xiàn),能夠訂閱和監(jiān)聽?wèi)?yīng)用中發(fā)生的各種事件。事件類通常存放在 app/Events 目錄下,而這些事件類的監(jiān)聽器則存放在 app/Listeners 目錄下。如果在你的應(yīng)用中你沒有看到這些目錄,不用擔(dān)心,它們會(huì)在你使用 Artisan 控制臺(tái)命令生成事件與監(jiān)聽器的時(shí)候自動(dòng)創(chuàng)建。

事件系統(tǒng)為應(yīng)用各個(gè)方面的解耦提供了非常棒的方法,因?yàn)閱蝹€(gè)事件可以擁有多個(gè)互不依賴的監(jiān)聽器。舉個(gè)例子,你可能希望每次訂單發(fā)貨時(shí)向用戶推送一個(gè) Slack 通知。你可以簡(jiǎn)單地發(fā)起一個(gè)可以被監(jiān)聽器接收并轉(zhuǎn)化為 Slack 通知的 OrderShipped 事件,而不是將訂單處理代碼和 Slack 通知代碼耦合在一起。

注冊(cè)事件和監(jiān)聽器

Laravel 應(yīng)用中的 EventServiceProvider 為注冊(cè)所有的事件監(jiān)聽器提供了一個(gè)便利的場(chǎng)所。其中, listen 屬性包含了所有事件 (鍵) 以及事件對(duì)應(yīng)的監(jiān)聽器 (值) 的數(shù)組。當(dāng)然,你可以根據(jù)應(yīng)用的需要,添加多個(gè)事件到 listen 屬性包含的數(shù)組中。舉個(gè)例子,我們來(lái)添加一個(gè) OrderShipped 事件:

/**
 * 應(yīng)用程序的事件監(jiān)聽器映射
 *
 * @var array
 */
 protected $listen = [ 
    'App\Events\OrderShipped' => [    
        'App\Listeners\SendShipmentNotification',  
        ],
    ];

生成事件 & 監(jiān)聽器

當(dāng)然,手動(dòng)創(chuàng)建事件和監(jiān)聽器的文件是件麻煩事。而在這里,你只需要將監(jiān)聽器和事件添加到 EventServiceProvider 中,而后使用 event:generate 命令。這個(gè)命令會(huì)生成在 EventServiceProvider 中列出的所有事件和監(jiān)聽器。當(dāng)然,已經(jīng)存在的事件和監(jiān)聽器將保持不變:

php artisan event:generate

手動(dòng)注冊(cè)事件

通常,事件是在 EventServiceProvider$listen 數(shù)組中注冊(cè);然而,你也可以在 EventServiceProviderboot 方法中手動(dòng)注冊(cè)基于閉包的這些事件:

/**
 * 注冊(cè)應(yīng)用中的其它事件
 *
 * @return void
 */
 public function boot(){ 
    parent::boot();    
    Event::listen('event.name', function ($foo, $bar) {  
          //   
       });
  }

通配符事件監(jiān)聽器

你可以在注冊(cè)監(jiān)聽器時(shí)使用 * 作為通配符參數(shù),這樣可以在同一個(gè)監(jiān)聽器上捕獲多個(gè)事件。通配符監(jiān)聽器接收事件名作為其第一個(gè)參數(shù),并將整個(gè)事件數(shù)據(jù)數(shù)組作為其第二個(gè)參數(shù):

Event::listen('event.*', function ($eventName, array $data) { 
   //
});

定義事件

事件類是一個(gè)保存與事件相關(guān)信息的容器。例如,假設(shè)我們生成的 OrderShipped 事件接收一個(gè) Eloquent ORM 對(duì)象:

<?php
    namespace App\Events;
    use App\Order;
    use Illuminate\Queue\SerializesModels;
    class OrderShipped{ 
       use SerializesModels;    
       public $order;    
     /**
     * 創(chuàng)建一個(gè)事件實(shí)例。
     *
     * @param  \App\Order  $order
     * @return void
     */   
    public function __construct(Order $order) 
       {    
           $this->order = $order;  
        }
    }

如你所見,這個(gè)事件類中沒有包含其它邏輯。它只是一個(gè)購(gòu)買的 Order 的實(shí)例的容器。如果使用 PHP 的 serialize 函數(shù)序列化事件對(duì)象,事件使用的 SerializesModels trait 將會(huì)優(yōu)雅地序列化任何 Eloquent 模型。

定義監(jiān)聽器

接下來(lái),讓我們看一下例子中事件的監(jiān)聽器。事件監(jiān)聽器在 handle 方法中接收實(shí)例。 event:generate 命令會(huì)自動(dòng)加載正確的事件類,并且在 handle 方法中加入事件的類型提示。在 handle 方法中,你可以執(zhí)行任何必要的響應(yīng)事件的操作:

<?php
    namespace App\Listeners;
    use App\Events\OrderShipped;
    class SendShipmentNotification{  
      /**
     * 創(chuàng)建事件監(jiān)聽器。
     *
     * @return void
     */  
   public function __construct()
      {      
        // 
      }  
     /**
     * 處理事件。
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */ 
    public function handle(OrderShipped $event) 
       {    
           // 使用 $event->order 來(lái)訪問(wèn) order ...  
        }
     }

{tip} 你的事件監(jiān)聽器也可以在構(gòu)造函數(shù)中加入任何依賴關(guān)系的類型提示。所有的事件監(jiān)聽器都是通過(guò) Laravel 的 服務(wù)容器 來(lái)解析的,因此所有的依賴都將會(huì)被自動(dòng)注入。

停止事件傳播

有時(shí),你可以通過(guò)在監(jiān)聽器的 handle 方法中返回 false 來(lái)阻止事件被其它的監(jiān)聽器獲取。

事件監(jiān)聽器隊(duì)列

如果你的監(jiān)聽器中要執(zhí)行諸如發(fā)送電子郵件或進(jìn)行 HTTP 請(qǐng)求等比較慢的任務(wù),你可以選擇將其丟給隊(duì)列處理。在開始使用隊(duì)列監(jiān)聽器之前,請(qǐng)確保在你的服務(wù)器或者本地開發(fā)環(huán)境中能夠 配置隊(duì)列 并啟動(dòng)一個(gè)隊(duì)列監(jiān)聽器。

要指定監(jiān)聽器啟動(dòng)隊(duì)列,你可以在監(jiān)聽器類中增加 ShouldQueue 接口。由 Artisan 命令 event:generate 生成的監(jiān)聽器已經(jīng)將此接口導(dǎo)入到當(dāng)前命名空間中,因此你可以直接使用:

<?php
    namespace App\Listeners;
    use App\Events\OrderShipped;
    use Illuminate\Contracts\Queue\ShouldQueue;
    class SendShipmentNotification implements ShouldQueue{
        //
     }

就是這個(gè)!當(dāng)這個(gè)監(jiān)聽器被事件調(diào)用時(shí),事件調(diào)度器會(huì)自動(dòng)使用 Laravel 的 隊(duì)列系統(tǒng)。如果在隊(duì)列中執(zhí)行監(jiān)聽器時(shí)沒有拋出異常,任務(wù)會(huì)在執(zhí)行完成后自動(dòng)從隊(duì)列中刪除。

自定義隊(duì)列連接 & 隊(duì)列名稱

如果你想要自定義事件監(jiān)聽器所使用的隊(duì)列的連接和名稱,你可以在監(jiān)聽器類中定義 $connection, $queue$delay 屬性:

<?php
    namespace App\Listeners;
    use App\Events\OrderShipped;
    use Illuminate\Contracts\Queue\ShouldQueue;
    class SendShipmentNotification implements ShouldQueue{
       /**
     * The name of the connection the job should be sent to.
     *
     * @var string|null
     */  
   public $connection = 'sqs'; 
     /**
     * The name of the queue the job should be sent to.
     *
     * @var string|null
     */   
   public $queue = 'listeners';   
     /**
     * The time (seconds) before the job should be processed.
     *
     * @var int
     */ 
    public $delay = 60;
  }

手動(dòng)訪問(wèn)隊(duì)列

如果你需要手動(dòng)訪問(wèn)監(jiān)聽器下面隊(duì)列任務(wù)的 deleterelease 方法,你可以通過(guò)使用 Illuminate\Queue\InteractsWithQueue trait 來(lái)實(shí)現(xiàn)。這個(gè) trait 會(huì)默認(rèn)加載到生成的監(jiān)聽器中,并提供對(duì)這些方法的訪問(wèn):

<?php
    namespace App\Listeners;
    use App\Events\OrderShipped;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    class SendShipmentNotification implements ShouldQueue{
        use InteractsWithQueue;  
      /**
     * 處理事件。
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */   
    public function handle(OrderShipped $event)
        {     
           if (true) { 
                  $this->release(30);  
                  }  
          }
     }

處理失敗任務(wù)

有時(shí)事件監(jiān)聽器的隊(duì)列任務(wù)可能會(huì)失敗。如果監(jiān)聽器的隊(duì)列任務(wù)超過(guò)了隊(duì)列中定義的最大嘗試次數(shù),則會(huì)在監(jiān)聽器上調(diào)用 failed 方法。 failed 方法接收事件實(shí)例和導(dǎo)致失敗的異常作為參數(shù):

<?php
    namespace App\Listeners;use App\Events\OrderShipped;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    class SendShipmentNotification implements ShouldQueue{ 
       use InteractsWithQueue;   
       /**
     * 處理事件。
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */   
    public function handle(OrderShipped $event) 
       {    
           // 
        }  
    /**
     * 處理失敗任務(wù)。
     *
     * @param  \App\Events\OrderShipped  $event
     * @param  \Exception  $exception
     * @return void
     */  
    public function failed(OrderShipped $event, $exception)
        {   
             //  
         }
     }

分發(fā)事件

如果要分發(fā)事件,你可以將事件實(shí)例傳遞給輔助函數(shù) event 。該輔助函數(shù)將會(huì)把事件分發(fā)到所有該事件相應(yīng)的已經(jīng)注冊(cè)了的監(jiān)聽器上。 event 輔助函數(shù)可以全局使用,你可以在應(yīng)用中的任何位置進(jìn)行調(diào)用:

<?php
    namespace App\Http\Controllers;
    use App\Order;use App\Events\OrderShipped;
    use App\Http\Controllers\Controller;
    class OrderController extends Controller{   
       /**
     * 將傳遞過(guò)來(lái)的訂單發(fā)貨
     *
     * @param  int  $orderId
     * @return Response
     */   
   public function ship($orderId)
       {     
          $order = Order::findOrFail($orderId);        
          // 訂單發(fā)貨邏輯 ...        
          event(new OrderShipped($order));    
        }
       }

{tip} 在測(cè)試時(shí),只需要斷言特定事件被分發(fā),而不需要真正地觸發(fā)監(jiān)聽器。 Laravel 的 內(nèi)置測(cè)試輔助函數(shù) 可以輕松做到這一點(diǎn)。

事件訂閱者

編寫事件訂閱者

事件訂閱者是可以在自身內(nèi)部訂閱多個(gè)事件的類,即能夠在單個(gè)類中定義多個(gè)事件處理器。訂閱者應(yīng)該定義一個(gè) subscribe 方法,這個(gè)方法接收一個(gè)事件分發(fā)器實(shí)例。你可以調(diào)用給定事件分發(fā)器上的 listen 方法來(lái)注冊(cè)事件監(jiān)聽器:

<?php
    namespace App\Listeners;
    class UserEventSubscriber{  
      /**
     * 處理用戶登錄事件。
     */   
   public function onUserLogin($event) {}    
      /**
     * 處理用戶注銷事件。
     */   
   public function onUserLogout($event) {}   
    /**
     * 為訂閱者注冊(cè)監(jiān)聽器
     *
     * @param  \Illuminate\Events\Dispatcher  $events
     */   
    public function subscribe($events) 
       {      
         $events->listen(         
            'Illuminate\Auth\Events\Login',           
            'App\Listeners\UserEventSubscriber@onUserLogin'       
           );        
          $events->listen(         
             'Illuminate\Auth\Events\Logout',            
             'App\Listeners\UserEventSubscriber@onUserLogout'    
              );  
         }
      }

注冊(cè)事件訂閱者

在編寫完訂閱者之后,就可以通過(guò)事件分發(fā)器對(duì)訂閱者進(jìn)行注冊(cè)。你可以在 EventServiceProvider 中的 $subscribe 屬性中注冊(cè)訂閱者。例如,讓我們將 UserEventSubscriber 添加到數(shù)組列表中:

<?php
    namespace App\Providers;
    use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
    class EventServiceProvider extends ServiceProvider{   
     /**
     * 應(yīng)用中事件監(jiān)聽器的映射。
     *
     * @var array
     */   
   protected $listen = [  
         //  
        ];  
     /**
     * 需要注冊(cè)的訂閱者類。
     *
     * @var array
     */ 
    protected $subscribe = [ 
           'App\Listeners\UserEventSubscriber',   
          ];
      }
本文章首發(fā)在 LearnKu.com 網(wǎng)站上。