• ecshopx 事件监听与订阅


    事件系统
     
     
    事件系统介绍
     
    Laravel 为事件提供了一个简单的观察者实现,允许你在应用中订阅和监听各种发生的事件。 在 Laravel 中事件类通常放在 app/Events 目录下,这些事件类的监听器则放在 app/Listeners 目录下。而在 Ecshopx 中事件和监听器则放在 Bundle 对应的目录中。
    事件系统为应用各个方面的解耦提供了非常棒的方法,因为单个事件可以拥有多个互不依赖的监听器。
    举个例子,在电商系统中,订单完成时,可能希望向用户发送短信通知或者微信通知,同时还需要处理一些订单相关的逻辑。你可以简单地发起一个可以被监听器接收并转化为短信通知的 TradeFinishEvent 事件,而不是将订单处理代码和发送短信通知代码耦合在一起。
    定义事件
    事件类是一个保存与事件相关信息的容器。它保存在 Bundle 的 Events 目录中。例如,假设我们定义一个 TradeFinishEvent 事件,其接收一个 Trade Entity 对象:
    1
    <?php
    2
    3
    namespace OrdersBundle\Events;
    4
    5
    use App\Events\Event;
    6
    7
    class TradeFinishEvent extends Event
    8
    {
    9
    public $entities;
    10
    11
    /**
    12
    * Create a new event instance.
    13
    *
    14
    * @return void
    15
    */
    16
    public function __construct($eventData)
    17
    {
    18
    $this->entities = $eventData;
    19
    }
    20
    }
     
    Copied!
    如你所见,这个事件类中没有包含其它逻辑。它只是一个 Trade 的实例的容器。
    定义监听器
    事件监听器是一个特殊的 PHP 类,其包含了一个接受事件的 handle 方法,handle 方法中加入事件的类型提示。它保存在 Bundle 的 Listeners 目录中。例如,在订单完成时,我们会给用户发送一个微信的模板消息。
    1
    <?php
    2
    3
    namespace OrdersBundle\Listeners;
    4
    5
    use OrdersBundle\Events\TradeFinishEvent;
    6
    7
    class TradeFinishWxaTemplateMsg {
    8
    9
    /**
    10
    * Handle the event.
    11
    *
    12
    * @param TradeFinishEvent $event
    13
    * @return void
    14
    */
    15
    public function handle(TradeFinishEvent $event)
    16
    {
    17
    //...
    18
    }
    19
    }
     
    Copied!
    注册事件和监听器
    现在我们定义了一个订单完成的事件 TradeFinishEvent 和 一个订单完成时的监听器 TradeFinishWxaTemplateMsg,现在我们需要注册事件和监听器。
    在 Laravel 中事件和监听器注册是在 EventServiceProvider 类中完成的,在 ecshopx 中,我们可以把它们放在每个 Bundle 的 Provider 中。 Provider 放在 Providers 目录下。
    1
    <?php
    2
    3
    namespace OrdersBundle\Providers;
    4
    5
    use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
    6
    7
    class TradeFinishServiceProvider extends ServiceProvider
    8
    {
    9
    /**
    10
    * The event listener mappings for the application.
    11
    *
    12
    * @var array
    13
    */
    14
    protected $listen = [
    15
    'OrdersBundle\Events\TradeFinishEvent' => [
    16
    'OrdersBundle\Listeners\TradeFinishWxaTemplateMsg',
    17
    ],
    18
    ];
    19
    }
     
    Copied!
    其中, listen 属性包含了所有事件 (键) 以及事件对应的监听器 (值) 的数组。当然,你可以根据应用的需要,添加多个事件到 listen 属性包含的数组中。
    在注册完成之后,还需要将 TradeFinishServiceProvider 在 bootstrap/app.php 中:
    1
    $app->register(OrdersBundle\Providers\TradeFinishServiceProvider::class);
     
    Copied!
    分发事件
    如果要分发事件,你可以将事件实例传递给辅助函数 event。该辅助函数将会把事件分发到所有该事件相应的已经注册了的监听器上。event 辅助函数可以全局使用,你可以在应用中的任何位置进行调用:
    1
    event(new TradeFinishEvent($eventsParams));
     
    Copied!
    事件监听器队列(异步事件)
    如果你的监听器中要执行诸如发送电子邮件或发出 HTTP 请求之类的耗时任务,你可以将任务丢给队列处理。在开始使用队列监听器之前,请确保在你的服务器或者本地开发环境中能够 配置队列并启动一个队列监听器。
    要指定监听器启动队列,你可以在监听器类中实现 ShouldQueue 接口。同时需要继承 EspierBundle\Listeners\BaseListeners 类:
    1
    <?php
    2
    3
    namespace SystemLinkBundle\Listeners;
    4
    5
    // use OrdersBundle\Events\TradeFinishEvent;
    6
    use Illuminate\Contracts\Queue\ShouldQueue;
    7
    use EspierBundle\Listeners\BaseListeners;
    8
    9
    class TradeAftersaleCancelSendOme extends BaseListeners implements ShouldQueue {
    10
    11
    12
    protected $queue = 'default';
    13
    14
    /**
    15
    * Handle the event.
    16
    *
    17
    * @param TradeFinishEvent $event
    18
    * @return void
    19
    */
    20
    public function handle(TradeAftersalesCancelEvent $event)
    21
    {
    22
    23
    24
    return true;
    25
    }
    26
    }
     
    Copied!
    现在,当这个监听器被事件调用时,事件调度器会自动使用 Laravel 的队列系统自动排队。如果在队列中执行监听器时没有抛出异常,任务会在执行完成后自动从队列中删除。
    自定义队列连接 & 队列名称
    如果你想要自定义事件监听器所使用的队列的连接和名称,你可以在监听器类中定义 $connection, $queue 或 $delay 属性:
    1
    <?php
    2
    3
    namespace App\Listeners;
    4
    5
    use App\Events\OrderShipped;
    6
    use Illuminate\Contracts\Queue\ShouldQueue;
    7
    8
    class SendShipmentNotification implements ShouldQueue
    9
    {
    10
    /**
    11
    * 任务连接名称。
    12
    *
    13
    * @var string|null
    14
    */
    15
    public $connection = 'sqs';
    16
    17
    /**
    18
    * 任务发送到的队列的名称.
    19
    *
    20
    * @var string|null
    21
    */
    22
    public $queue = 'listeners';
    23
    24
    /**
    25
    * 处理任务的延迟时间.
    26
    *
    27
    * @var int
    28
    */
    29
    public $delay = 60;
    30
    }
     
    Copied!
    处理失败任务
    有时事件监听器的队列任务可能会失败。如果监听器的队列任务超过了队列中定义的最大尝试次数,则会在监听器上调用 failed 方法。 failed 方法接收事件实例和导致失败的异常作为参数:
    1
    <?php
    2
    3
    namespace App\Listeners;
    4
    5
    use App\Events\OrderShipped;
    6
    use Illuminate\Queue\InteractsWithQueue;
    7
    use Illuminate\Contracts\Queue\ShouldQueue;
    8
    9
    class SendShipmentNotification implements ShouldQueue
    10
    {
    11
    use InteractsWithQueue;
    12
    13
    /**
    14
    * 处理事件.
    15
    *
    16
    * @param \App\Events\OrderShipped $event
    17
    * @return void
    18
    */
    19
    public function handle(OrderShipped $event)
    20
    {
    21
    //
    22
    }
    23
    24
    /**
    25
    * 处理失败任务
    26
    *
    27
    * @param \App\Events\OrderShipped $event
    28
    * @param \Exception $exception
    29
    * @return void
    30
    */
    31
    public function failed(OrderShipped $event, $exception)
    32
    {
    33
    //
    34
    }
    35
     
  • 相关阅读:
    最佳实践丨三种典型场景下的云上虚拟IDC(私有池)选购指南
    总渲染时长超3亿核小时,阿里云助力《白蛇2:青蛇劫起》提升视效
    阿里云成为首个通过“虚拟化云平台性能测试(大规模)”的云厂商
    AI性能提升2-3倍!搭载 NVIDIA A10 GPU的阿里云gn7i服务器开启邀测
    最佳实践丨阿里云ECI如何助力西软构建酒店行业多租户高弹性PaaS平台?
    暑期大放“价”,轻量应用服务器9元包月!
    报名通道开启!原生安全二倍速:探秘基础设施的内生“免疫系统"
    40万奖金等你来挑战!阿里云ECS Cloudbuild开发者大赛重磅开启
    Ubuntu安装桌面环境
    tinkphp3.0 execl导出问题
  • 原文地址:https://www.cnblogs.com/showker/p/15955445.html
Copyright © 2020-2023  润新知