1. 程式人生 > >laravel5.5事件系統

laravel5.5事件系統

1 註冊事件和監聽器

1、修改EventServiceProvider中的listen陣列

/**
 * 應用程式的事件監聽器對映。
 *
 * @var array
 */
protected $listen = [
    'App\Events\OrderShipped' => [
        'App\Listeners\SendShipmentNotification',
    ],
];

2、建立相應檔案

php artisan event:generate

執行上面命令後,根據上面修改的listen陣列,會在app目錄下會生成相應的資料夾和檔案

2 定義事件

修改App\Events\OrderShipped.php檔案

<?php

namespace App\Events;

use App\Order;
use Illuminate\Queue\SerializesModels;

class OrderShipped
{
    use SerializesModels;

    public $order;

    /**
     * 建立一個事件例項。
     *
     * @param  Order  $order
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }
}

3 定義監聽器

<?php

namespace App\Listeners;

use App\Events\OrderShipped;

class SendShipmentNotification
{
    /**
     * 建立事件監聽器。
     *
     * @return void
     */
    public function __construct()
    {
        //你的事件監聽器也可以在建構函式中加入任何依賴關係的型別提示。
        //所有的事件監聽器都是通過 Laravel 的 服務容器 來解析的,因此所有的依賴都將會被自動注入。
    }

    /**
     * 處理事件
     *
     * @param  OrderShipped  $event
     * @return void
     */
    public function handle(OrderShipped $event)
    {
        /********************************************
        *    
        * 1.當你分發事件之後,這裡你可以實現你想做的事情 ...
        * 2.如果一個事件有多個監聽器,這裡返回false則不會再被其他的監聽器獲取
        */
        
        //用 $event->order 來訪問 order ...
        dd($event);
        //return false;
    }
}

4 分發事件

可以使用全域性輔助函式event(),可以在應用的任何地方使用,將事件分發給已經註冊的監聽器上。

<?php

namespace App\Http\Controllers;

use App\Order;
use App\Events\OrderShipped;
use App\Http\Controllers\Controller;

class OrderController extends Controller
{
    public function ship($orderId)
    {
        $order = Order::findOrFail($orderId);
        
        //分發事件,最後dd()打印出$order
        event(new OrderShipped($order));
    }
}

更多使用方法

1. 可以手動註冊事件

事件通常是像上面那樣在$listen陣列中定義, 但是,也可以在 EventServiceProvider 類的 boot 方法中註冊基於事件的閉包

/**
 * 註冊應用程式中的任何其他事件。
 *
 * @return void
 */
public function boot()
{
    parent::boot();

    Event::listen('event.name', function ($foo, $bar) {
        //
    });
    
    //這裡還可以使用萬用字元*,在此監聽多個事件。
    //萬用字元監聽器接受事件名稱作為其第一個引數,並將整個事件資料陣列作為其第二個引數:
    
    Event::listen('event.*', function ($eventName, array $data) {
    //
});
}

2. 事件監聽器中呼叫佇列

1、如果需要使用比較發郵件等比較慢的任務,則可以丟給佇列處理

只需要將讓監聽類實現ShouldQueue介面

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    //
}

2、可以自定義佇列連線和名稱

監聽器類中定義 $connection 和 $queue 屬性即可

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    /**
     * 任務應該傳送到的佇列的連線的名稱
     *
     * @var string|null
     */
    public $connection = 'sqs';

    /**
     * 任務應該傳送到的佇列的名稱
     *
     * @var string|null
     */
    public $queue = 'listeners';
}

3、手動訪問佇列

如果你需要手動訪問監聽器下面佇列任務的 delete 和 release 方法,你可以新增 Illuminate\Queue\InteractsWithQueue trait 來實現。這個 trait 會預設載入到生成的監聽器中,並提供對這些方法的訪問:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    use InteractsWithQueue;

    /**
     * Handle the event.
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */
    public function handle(OrderShipped $event)
    {
        if (true) {
            $this->release(30);
        }
}

4、處理失敗佇列

事件監聽器的佇列任務可能會失敗,而如果監聽器的佇列任務超過了佇列中定義的最大嘗試次數,則會監聽器上呼叫 failed 方法。failed 方法接受接收事件例項和導致失敗的異常作為引數:

<?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)
    {
        //
    }

    /**
     * 處理任務失敗
     *
     * @param  \App\Events\OrderShipped  $event
     * @param  \Exception  $exception
     * @return void
     */
    public function failed(OrderShipped $event, $exception)
    {
        //
    }
}

3.事件訂閱者

1、編寫事件訂閱者類

事件訂閱者是一個可以在自身內部訂閱多個事件的類,即能夠在單個類中定義多個事件處理器。訂閱者應該定義一個 subscribe 方法,這個方法接受一個事件分發器的例項。你可以呼叫給定的事件分發器上的 listen 方法來註冊事件監聽器:

<?php

namespace App\Listeners;

class UserEventSubscriber
{
    /**
     * 處理使用者登入事件。
     */
    public function onUserLogin($event) {}

    /**
     * 處理使用者登出事件。
     */
    public function onUserLogout($event) {}

    /**
     * 為訂閱者註冊監聽器。
     *
     * @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'
        );
    }

}

2、註冊事件訂閱者

在 EventServiceProvider 類的 $subscribe 屬性中註冊訂閱者

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * 應用中事件監聽器的對映。
     *
     * @var array
     */
    protected $listen = [
        //
    ];

    /**
     * 需要註冊的訂閱者類。
     *
     * @var array
     */
    protected $subscribe = [
        'App\Listeners\UserEventSubscriber',
    ];
}