使用事件,可以在特定的时点,触发执行预先设定的一段代码,事件既是代码解耦的一种方式,也是设计业务流程的一种模式。现代软件中,事件无处不在,比如,你发了个微博,触发了一个事件,导致关注你的人,看到了你新发出来的内容。 —- 深入理解 Yii2.0
对于任务而言,意味着代码会通知应用程序应执行什么操作:CrunchReports 或 NotifyAdminOfNewSignup
对于事件而言,意味着代码将通知应用程序发生了什么事情:UserSubscribed 或 UserSignedUp 或 ContactWawego。事件是已经发生某事的通知。
其中一些事件可能会被框架本身“触发”。例如,Eloquent modelss 在保存,创建或删除事件时都会触发事件。但是,还有一些事件可以由应用程序的代码手动触发。
触发事件本身并不会做任何事情。但是,您可以绑定事件侦听器,其唯一目的是侦听特定事件的广播并做出响应。任何事件都可以有零到多个事件侦听器。
Laravel的事件的结构类似于观察者或“发布/订阅”模式。许多事件在应用程序中被触发。有些可能永远不会被监听,而另一些可能会有十几个监听者。这些事件不需要知道或关心。
触发事件
有三种方式触发事件:
// Event facade 方式Event::fire(new UserSubscribed($user, $plan));// 注入 Dispatcher 方式$dispatcher = app(Illuminate\Contracts\Events\Dispatcher::class);$dispatcher->fire(new UserSubscribed($user, $plan));// 全局函数的方式event(new UserSubscribed($user, $plan));
创建事件
php artisan make:event UserSubscribed
使用以上命令将创建一个事件。
你可能奇怪怎么没有 handle() 或者 fire() 。记住,这个对象的存在不是为了,确定特定的动作,而是封装一些数据。第一条数据是它的名字,UserSubscribed 告诉我们一个特定的事件(一个用户订阅了)发生了。其余的数据就是我们传入构造函数,并与此实体相关联的任何其他数据。
// ...
class UserSubscribed
{
use InteractsWithSockets, SerializesModels;
public $user;
Public $plan;
public function __construct($user, $plan){
$this->user = $user;
$this->plan = $plan;
}
}
现在我们有了一个对象,可以合适的表示发生的事件:$event->user 订阅了 $event->plan 的计划。请记住,触发事件也很简单 (new UserSubscribed($user, $plan))。
监听事件
现在我们已经有了一个事件,并且可以触发它。现在让我们看看怎么监听它。
首先,创建一个事件监听者. 例如,每当新的用户订阅时,就发给 app 拥有者一个 email 通知:
php artisan make:listener EmailOwnerAboutSubscription --event=UserSubscribed
这里是具体代码执行的地方——这里有一个 handle() 方法。这个方法接收一个 UserSubscribed 类型的事件,并对事件作出反应。
use App\Mail\UserSubscribed as UserSubscribedMessage;
class EmailOwnerAboutSubscription{
public function handle(UserSubscribed $event){
Log::info('Emailed owner about new user: '. $event->user->email);
Mail::to(config('app.owner-email'))
->send(new UserSubscribedMessage($event->user, $event->plan));
}
}
现在还有最后一个任务,设置监听者监听这个事件(UserSubscribed). 我们配置 EventServiceProvider 类的 $listen 属性即可。
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
\App\Events\UserSubscribed::class => [
\App\Listeners\EmailOwnerAboutSubscription::class,
],
];
}
如上,key 是事件名,value 是监听者数组。我们可以添加多个监听者在 UserSubscribed 键之下,他们都会监听并响应这个事件。
事件订阅者
在事件和监听者之间你可以定义的不止一种关系。Laravel 有一个 event subscriber 的概念, 它是一个类,包含了一个集合,有独立的事件监听者的处理方法,还有哪个方法处理哪个事件的映射关系。如下:
<?php
namespace App\Listeners;
class UserEventSubscriber
{
public function onUserSubscription($event){
// 处理 UserSubscribed 事件
}
public function onUserCancellation($event){
// 处理 UserCanceled 事件
}
public function subscribe($event){
$event->listen(
\App\Events\UserSubscribed::class,
'App\Listeners\UserEventSubscriber@onUserSubscription'
);
$events->listen(
\App\Events\UserCanceled::class,
'App\Listeners\UserEventSubscriber@onUserCancellation'
);
}
}
ps: 事件订阅者不是特别常用的工具。
事件订阅者需要定义一个 subscribe 方法,接受一个事件调度者实例对象。我们使用它来将事件和他们的监听者配对,在这里,监听者只是一个方法,而非整个类。
还有最后一件事情要做:到 App\Providers\EventServicePrivider 中, 添加我们的事件订阅者到 $subscribe 属性,如下:
class EventServiceProvider extends ServiceProvider
{
// ...
protected $subscribe = [
\App\Listeners\UserEventSubscriber::class
];
}
