简介

Laravel 事件提供了简单的观察着模式实现,允许你订阅和监听应用中的事件。事件类通常存放在 app/Events 目录。

监听器存放在 app/Listeners. 如果你在应用中没有看到这些目录,不要担心,他们会在你使用Artisan命令生成事件和

监听器的时候自动创建。

事件为应用功能模块解耦提供了行之有效的解决方法,因为单个事件可以有多个监听器而这些监听器之间并不相互依赖。

例如,你可能想要在每次订单发送时给用户发送一个Slack通知,有了事件之后,你大可不必将订单处理代码和Slack

通知代码耦合在一起,而只需要简单触发一个可以被监听器接收并处理为Slack通知的 OrderShipped 事件即可。

注册事件/监听器

Laravel自动的 EventServerProvider 为时间监听其注册提供了方便之所。其中的listen属性包含了事件(键)和对应

监听器(值)数组.如果应用需要,你可以添加多个事件到给数组。下面让我们添加一个 OrderShipped事件:

生成事件/监听器类

当然,手动为每个事件和监听器创建文件是很笨重的,取而代之的,我们只需简单添加监听器和事件到EventServiceProvider

然后运行 event:generate 命令。该命令将会生成罗列在EventServiceProider 中的所有事件和监听器。当然,已存在

的事件和监听器不会被重复创建:

php artisan event:generate

手动注册事件

通常,我们需要通过 EventServiceProider 的$listen 数组注册事件,此外,你还可以在EventServiceProvider 的

boot方法中手动注册基于闭包的事件:

通配符事件监听器

你甚至还可以使用通配符*来注册监听器,这样就可以通过同一个监听器捕获多个事件。通配符监听器接收整个

事件数据数组作为参数:

定义事件

事件类是一个处理与事件相关的简单数据容器,例如,假设我们生成的 OrderShipped事件接收一个Eloquent ORM

对象:

<?php

namespace App\Events;

use App\Order;

use Illuminate\Queue\SerializesModels;

class OrderShipped

{

use SerializesModels;

public $orders;

/*

创建一个新的实践实例

@param Order $order

@return void

*/

public function __construct(Order $order)

{

  $this->order = $order;

}

正如你所看到的,该事件类不包含任何特定逻辑,只是一个存放被购买的Order对象的容器,如果时间对象被序列化的话,

事件使用的SerializeModels trait 将会使用过PHP的serialize函数序列化所有Eloquent模型。

定义监听器

接下来,让我们看看实例事件的监听器,事件监听器在 handle方法中接收事件实例,event:generate 命令将会自动

在 handle方法中导入相应的事件类和类型提示事件。在handle方法内,你可以执行任何需要的逻辑以响应时间:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;

class SendShipmentNotification

{

/*

  创建事件监听器

@return void

*/

public function __construct()

{

}

/*

处理事件

@param OrderShipped $event

@return void

*/

public funcion handle(OrderShipped $event)

{

  //使用 $event->order 发访问订单...

}

}

?>

注: 事件监听器还可以在构造器中类型提示任何需要的依赖,所有事件监听器通过服务器解析,所以依赖会自动注入。

停止事件继续往下传播

有时候,你希望停止事件被传播到其他监听器,你可以通过从监听器的handle方法中返回false来实现。

事件监听器队列

如果监听器将要执行耗时任务比如发送邮件或者发送HTTP请求,那么将监听器放到队列是一个不错的选择。在队列化

监听器之前,确保已经配置好队列并且在服务器或本地环境启动一个队列监听器。

要指定某个监听器需要放到队列,只需要让监听器类实现 ShouldQueue 接口即可,通过Artisan命令event:generate

生成的监听器类已经将这个接口导入当前命名空间,所以你可以直接拿来使用:

<?php

namespace App\Listeners;

user App\Events\OrdersShipped;

use Illuminate\Contracts\Queue\ShowldQueue;

class SendShipmentNotification implements ShouldQueue

{

//

}

就是这么简单!当这个监听器被调用的时候,将会使用Laravel的队列系统通过事件分发器自动推送到队列。如果通过队列

执行监听器的时候没有抛出任何异常,队列任务会在执行完成后被自动删除。

自定义队列链接&队列名称

如果你想要自定义事件监听器使用的队列链接和队列名称,可以在监听器类中定义$connection 和$queue属性:

<?php

namespace App\Listeners;

use App\Events\OrdersShipped;

use Illuminate\Contracts\Queue\ShouldQueue

{

  /*

  任务将被推送到的链接名称

*/

  public $connection = 'sqs';

  /*

  任务将被推送到的链接名称

  @var string|null

  */

  public $queue = 'listeners';

}

手动访问队列

如果你需要手动访问底层队列任务的delete和release方法,在生成的监听器中,默认导入的Illuminate\Queue\InteractsWithQueue

trait 为这两个方法提供了访问权限:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;

use Illuminate\Queue\InteractsWidthQueue;

use Illuminate\Contracts\Queue\ShowldQueue;

class SendShipmentNotification implements ShowldQueue

{

  use InteractsWithQueue;

  public function handle(OrderShipped $event)

  {

    if(true){

    $this->release(30);

  }

  }

}

处理失败任务

有时候队列中的事件监听器可能会执行失败。如果队列中的监听器任务执行时超出了队列进程定义的最大尝试次数,监听器上的

failed方法会被调用,failed方法接收事件实例和导致失败的异常:

分发事件

要分发一个事件,可以传递事件实例到辅助函数event,这个辅助函数会分发事件到所有注册的监听器。由于辅助函数恶女他

全局有效,所以可以在应用的任何地方调用它:

注: 测试的时候,只需要断言特定事件被分发,无需真正触发监听器,Laravel自带的测试函数让这一实现轻而易举

事件订阅者

编写事件订阅者

事件订阅者是指那些在类本身中订阅多个事件的类,通过事件订阅者你可以在单个类中定义多个事件处理器。订阅者需要定义一个

subscibe 方法,该方法中传入一个事件分发器实例。你可以在给定的分发器汇总调用listen方法注册事件监听器

laravel进阶系列--通过事件和事件监听实现服务解耦的更多相关文章

  1. SpringBoot系列——事件发布与监听

    前言 日常开发中,我们经常会碰到这样的业务场景:用户注册,注册成功后需要发送邮箱.短信提示用户,通常我们都是这样写: /** * 用户注册 */ @GetMapping("/userRegi ...

  2. spring中的事件发布与监听

    点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. spring事件发布与监听的应用场景 当处理完一段代码逻辑,接下来需要同 ...

  3. 关于JAVA中事件分发和监听机制实现的代码实例-绝对原创实用

    http://blog.csdn.net/5iasp/article/details/37054171 文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.c ...

  4. Pox启动及事件产生、监听分析

        ./pox/pox.py , Pox       实例化core=pox.core.initialize(),即为实例化POXCore类(该类是所有组件的交接点,提供组件注册功能),监听cor ...

  5. JavaEE开发之Spring中的事件发送与监听以及使用@Profile进行环境切换

    本篇博客我们就来聊一下Spring框架中的观察者模式的应用,即事件的发送与监听机制.之前我们已经剖析过观察者模式的具体实现,以及使用Swift3.0自定义过通知机制.所以本篇博客对于事件发送与监听的底 ...

  6. Spring知识点回顾(07)事件发布和监听

    Spring知识点回顾(07)事件发布和监听 1.DemoEvent extends ApplicationEvent { public DemoEvent(Object source, String ...

  7. spring 自定义事件发布及监听(简单实例)

    前言: Spring的AppilcaitionContext能够发布事件和注册相对应的事件监听器,因此,它有一套完整的事件发布和监听机制. 流程分析: 在一个完整的事件体系中,除了事件和监听器以外,还 ...

  8. apiCloud事件发送与监听

    apiCloud事件发送与监听 1.sendEvent 将任意一个自定义事件广播出去,该事件可在任意页面通过 addEventListener 监听收到. sendEvent({params}) 2. ...

  9. Spring事件发布与监听机制

    我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. 目录 ...

随机推荐

  1. Spring Bean 作用域

    Bean 的作用域 当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项.例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean ...

  2. windows device recovery tool 刷机

    ch 春节期间,拿出来诺基亚1020拍照,误删软件,无法登陆微软账号,考虑刷机处理 下载windows device recovery tool,进行刷机,但是固件下载一直失败 考虑下载好固件包,ff ...

  3. day36 09-Hibernate中的事务:事务处理

    什么是丢失更新呢?有一条数据你查出来了,查出来之后有一个事务A和一个事务B也都过来操作同一个记录.A拿到这条记录之后可能改它的某一个值了,B拿到这条记录之后改它的另外一个值.这个时候A事务提交已经提交 ...

  4. UVA1204 Fun Game

    Fun Game https://odzkskevi.qnssl.com/8d698323a1e07d605cdeea708ee8a01d?v=1508703139 [题解] 不难发现如果一个串的原串 ...

  5. 八.DBN深度置信网络

    BP神经网络是1968年由Rumelhart和Mcclelland为首的科学家提出的概念,是一种按照误差反向传播算法进行训练的多层前馈神经网络,是目前应用比较广泛的一种神经网络结构.BP网络神经网络由 ...

  6. NodeJs的简介及安装

    首先 分享一下NodeJs的应用场景吧: Web聊天室(IM):Express + Socket.io socket.io一个是基于Nodejs架构体系的,支持websocket的协议用于时时通信的一 ...

  7. 【JZOJ4755】【NOIP2016提高A组模拟9.4】快速荷叶叶变换

    题目描述 输入 一行,包含两个整数N,M. 输出 1个整数,FHT(N,M) mod 1000000007的值. 样例输入 3 4 样例输出 1 数据范围 对于 40% 的数据,1 ≤ N,M ≤ 1 ...

  8. jdbc框架-dbutils的简单使用

    jdbc框架-dbutils的简单使用 dbutils:是apache组织的一个工具类,jdbc的框架,更方便我们使用 使用步骤: 1.导入jar包(commons-dbutils-1.4.jar) ...

  9. PersistGate轻松几步让Redux实现数据持久化

    在开发的过程中,数据用redux管理,觉得希望将数据持久化保存,也就是说当用户下一次打开app或网站的时候,我们希望浏览器/APP自动加载出上次的数据,怎么办?有没有一个

  10. python三种导入模块的方法和区别

    方法一: import modname 模块是指一个可以交互使用,或者从另一Python 程序访问的代码段.只要导入了一个模块,就可以引用它的任何公共的函数.类或属性.模块可以通过这种方法来 使用其它 ...