事件原理:通过观察者模式,实现的事件订阅,事件的监听。

事件目录:/app/Events

监听目录:/app/Listeners


创建事件与监听

创建一对事件和它的监听器:

php artisan make:event MyEvent
php artisan make:listener MyListener --event=MyEvent

生成两个文件:

/app/Events/MyEvent.php

<?php
namespace App\Events;
use ...

class MyEvent{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function broadcastOn(){
return new PrivateChannel('channel-name');
}
}

/app/Lisnteners/MyListener.php

<?php
namespace App\Listeners;
use ...

class MyListener{
//当事件发生时,该监听器执行的方法,返回 false 将中断事件传递
public function handle(MyEvent $event){

}
}

注册事件与监听

/app/Providers/EventServiceProvider.php  用来注册事件与监听器

<?php
namespace App\Providers;
use ...

class EventServiceProvider extends ServiceProvider{
//这里注册事件与监听的映射,格式:['事件'=>['监听1','监听2']],
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],

//方式一
MyEvent::class => [MyListener::class],
];

//也可以在这里注册
public function boot(){
//方式二
Event::listen(MyEvent::class, [MyListener::class, 'handle']);

//方式三:闭包监听
Event::listen(function (MyEvent $event) {});

//方式四:通配映射
Event::listen('event.*', function (MyEvent, array $data) {});

//方式五:监听队列,需要配置队列服务
Event::listen(queueable(function (MyEvent $event) {})
->onConnection('redis')
->onQueue('podcasts')
->delay(now()->addSeconds(10))
->catch(function (MyEvent $event, Throwable $e) {
//监听失败
}));
}

//是否自动发现事件和监听器,这样注册的监听器,通过参数类型来判断要监听的事件
public function shouldDiscoverEvents(){
return false;
}
}

使用监听队列(二)

实现 ShouldQueue 接口

<?php
namespace App\Listeners;
use ...

class MyListener implements ShouldQueue{

//访问队列
use InteractsWithQueue;

//提交完事物再被调度
public $afterCommit = true;

//队列连接的名称
public $connection = 'sqs';
//队列的名称
public $queue = 'listeners';
//队列处理的延迟(秒)
public $delay = 60;
//失败尝试上限
public $tries = 5;


//是否使用队列,返回 false 则不
public function shouldQueue(MyEvent $event){
return $event->order->subtotal >= 5000;
}

//事件处理
public function handle(MyEvent $event){

}

//监听失败
public function failed(OrderShipped $event, $exception){

}

//监听超时,过时不再尝试监听
public function retryUntil(){
return now()->addMinutes(5);
}
}

事件调用

事件和监听器编写并注册以后,就可以在业务流程里面调用了,事件和监听器都会被顺序地调用:

MyEvent::dispatch();

事件订阅

除了监听器,也可以使用订阅来处理事件的后续操作,可以处理多个事件。

<?php
namespace App\Listeners;
use ...

class MySubscriber{
//1事件
public function handle1($event) {}

//2事件
public function handle2($event) {}

//事件订阅
public function subscribe($events){
//格式一
$events->listen(Event1::class, [MySubscriber::class, 'handle1']);
$events->listen(Event2::class, [MySubscriber::class, 'handle2']);

//格式二
return [
Login::class => 'handleUserLogin',
Logout::class => 'handleUserLogout',
];
}
}

注册订阅者

和注册事件、监听器是一个文件:/app/Providers/EventServiceProvider.php

不同的是,注册者写在 $subscribe 属性的数组中:

<?php
protected $subscribe = [
UserEventSubscriber::class,
];