作为程序员一定要保持良好的睡眠,才能好编程

laravel事件系统 事件及监听器6.0以上版本

发布时间:2020-01-30



事件系统:https://learnku.com/docs/laravel/6.x/events/5162


事件系统介绍


Laravel 的事件提供了一个简单的观察者实现,允许你在应用中订阅和监听各种发生的事件。事件类通常放在 app/Events 目录下,而这些事件类的监听器则放在 app/Listeners 目录下。如果在你的应用中你没有看到这些目录,不用担心,它们会在你使用 Artisan 控制台命令生成事件与监听器的时候自动创建


事件系统为应用各个方面的解耦提供了非常棒的方法,因为单个事件可以拥有多个互不依赖的监听器。


注册事件和监听器


Laravel 应用中的 EventServiceProvider 为注册所有的事件监听器提供了一个便利的场所。其中, listen 属性包含了所有事件 (键) 以及事件对应的监听器 (值) 的数组。当然,你可以根据应用的需要,添加多个事件到 listen 属性包含的数组中。举个例子,


image.png



通过上边的命令已经自动创建好了监听器和事件。






事件发现

注意:事件发现可用于 Laravel 5.8.9 或更高版本。


您可以启用自动事件发现,而不是在 EventServiceProvider 的 $listen 数组中手动注册事件和监听器。 启用事件发现后,Laravel 将通过扫描应用程序的 Listeners 目录自动查找并注册您的事件和侦听器。 此外,EventServiceProvider 中列出的任何明确定义的事件仍将被注册。


Laravel 通过使用反射扫描监听器类来查找事件监听器。

 当 Laravel 找到以 handle 开头的监听器类方法时,Laravel 会将这些方法注册为方法签名中类型提示的事件的事件监听器:


use App\Events\PodcastProcessed;


class SendPodcastProcessedNotification

{

    /**

     * 处理给定的事件。

     *

     * @param  \App\Events\PodcastProcessed

     * @return void

     */

    public function handle(PodcastProcessed $event)

    {

        //

    }

}


默认情况下是禁用事件发现的,但可以通过覆盖应用程序的 EventServiceProvider 的 shouldDiscoverEvents 方法来启用它:


/**

 * 确定是否应自动发现事件和侦听器。

 *

 * @return bool

 */

public function shouldDiscoverEvents()

{

    return true;

}

默认情况下,将扫描应用程序的 Listeners 目录中的所有监听器。 如果要定义扫描的其他目录,可以覆盖 EventServiceProvider 中的 discoverEventsWithin 方法:


/**

 * 获取应该用于发现事件的监听器目录

 *

 * @return array

 */

protected function discoverEventsWithin()

{

    return [

        $this->app->path('Listeners'),

    ];

}

在生产中,您可能不希望框架在每个请求上扫描所有监听器。 

因此,在部署过程中,

您应该运行 event:cache Artisan 命令来缓存应用程序的所有事件和监听器的列表。

框架将使用此列表来加速事件注册过程。 

event:clear 命令可用于销毁缓存。



自定义事件


事件类是一个保存与事件相关信息的容器。例如,假设我们生成的 OrderShipped 事件接收一个 Eloquent ORM 对象:


<?php

namespace App\Events;

use App\Models\Inquiry\OutPatientOrderModel;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class OrderShipped
{
    public $order;
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @param OutPatientOrderModel $order
     */
    public function __construct(OutPatientOrderModel $order)
    {
        $this->order = $order;
    }

}


如你所见,这个事件类中没有包含其它逻辑。它只是一个购买的 Order 的实例的容器。如果使用 PHP 的 serialize 函数序列化事件对象,事件使用的 SerializesModels trait 将会优雅地序列化任何 Eloquent 模型。


定义监听器

接下来,让我们看一下例子中事件的监听器。

事件监听器在 handle 方法中接收实例。 event:generate 命令会自动加载正确的事件类,

并且在 handle 方法中加入事件的类型提示。

在 handle 方法中,你可以执行任何必要的响应事件的操作:


代码:

<?php
namespace App\Listeners;
use App\Events\OrderShipped;
class SendShipmentNotification
{
    /**
     * 创建事件监听器
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * 处理事件
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */
    public function handle(OrderShipped $event)
    {
         // 使用 $event->order 来访问 order ...
    }
}

image.png



提示:你的事件监听器也可以在构造函数中加入任何依赖关系的类型提示。

所有的事件监听器都是通过 Laravel 的 服务容器解析的,因此所有的依赖都将会被自动注入.



停止事件传播

有时,你可以通过在监听器的 handle 方法中返回 false 来阻止事件被其它的监听器获取。


如果某个事件执行失败,则可以在handle中方法中返回false,阻止后续的事件执行。




事件监听器队列

如果你的监听器中要执行诸如发送电子邮件或发出 HTTP 请求之类的耗时任务,你可以将任务丢给队列处理。

在开始使用队列监听器之前,请确保在你的服务器或者本地开发环境中能够 配置队列并启动一个队列监听器。


要指定监听器启动队列,你可以在监听器类中实现 ShouldQueue 接口。

由 Artisan 命令 event:generate 生成的监听器已经将此接口导入到当前命名空间中,

因此你可以直接使用:




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


That's it! 现在,当这个监听器被事件调用时,事件调度器会自动使用 Laravel 的队列系统自动排队。如果在队列中执行监听器时没有抛出异常,任务会在执行完成后自动从队列中删除。



分发事件 事件调用 event 函数

如果要分发事件,你可以将事件实例传递给辅助函数 event。

该辅助函数将会把事件分发到所有该事件相应的已经注册了的监听器上。

event 辅助函数可以全局使用,你可以在应用中的任何位置进行调用:


<?php
namespace App\Http\Controllers;
use App\Order;
use App\Events\OrderShipped;
use App\Http\Controllers\Controller;
class OrderController extends Controller
{
    /**
     * 将传递过来的订单发货
     *
     * @param  int  $orderId
     * @return Response
     */
    public function ship($orderId)
    {
        $order = Order::findOrFail($orderId);
        // Order shipment logic...
        event(new OrderShipped($order));
    }
}


也可以使用这样的方式进行访问:

\Illuminate\Support\Facades\Event::fire(new \App\Events\OrderShipped());


6.0以上版本

\Illuminate\Support\Facades\Event::until(new \App\Events\OrderShipped());




事件系统异步执行


1、监听器必须是实现ShouldQueue 这个接口

2、必须配置了队列,如使用db 或reids

3、启动了一个消费脚本


队列文档请参考:https://learnku.com/docs/laravel/6.x/queues/5168



curl请求:

$ curl http://localhost:8084/event_test



网上案例:


https://www.cnblogs.com/sweng/p/6358961.html


更加详细介绍了event的好处:

https://www.cnblogs.com/yulibostu/articles/10756155.html