Fork me on GitHub

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',
    ];
}
posted @ 2018-02-09 16:02  archer-wong  阅读(1878)  评论(0编辑  收藏  举报