Laravel 事件系统用法总结

Laravel 的事件提供了一个简单的观察者实现,可以订阅和监听应用中发生的各类事件。事件类保存在 app/Events 目录中,而这些事件的的监听器则被保存在 app/Listeners 目录下。这些目录只有当你使用 Artisan 命令来生成事件和监听器时才会被自动建立。php

事件机制是一种很好的应用解耦方式,由于一个事件能够拥有多个互不依赖的监听器。例如,若是你但愿每次订单发货时向用户发送一个 Slack 通知。你能够简单地发起一个 OrderShipped 事件,让监听器接收以后转化成一个 Slack 通知,这样你就能够不用把订单的业务代码跟 Slack 通知的代码耦合在一块儿了。laravel

生成一个事件类

好比经过 artisan 命令生成一个 UserLogin 事件:redis

php artisan make:event UserLogin
复制代码

在 app/Events 中就会自动生成一个 UserLogin.php 文件,内容很少,以下:bash

<?php
 
namespace App\Events;
 
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
 
class UserLogin
{
    use InteractsWithSockets, SerializesModels;
 
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
 
    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}
复制代码

定义监听器

一个事件能够被一个或多个监听器监听,也就是观察者模式,咱们能够定义多个监听器,当这个事件发生,执行一系列逻辑。app

在 EventServiceProvider 的 $listen 中能够定义事件和监听器,以下:异步

protected $listen = [
    'App\Events\UserLogin' => [
        'App\Listeners\DoSomething1',
        'App\Listeners\Dosomething2',
    ],
];
复制代码

而后执行 artisan 命令,就能够自动在 app/Listeners 目录生成监听器。socket

php artisan event:generate
复制代码

能够看到 app/Listeners 目录多了 DoSomething1.php 和 DoSomething2.php 两个文件,咱们看看其中一个内容:ide

<?php
 
namespace App\Listeners;
 
use App\Events\UserLogin;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
 
class DoSomething1
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
 
    /**
     * Handle the event.
     *
     * @param  UserLogin  $event
     * @return void
     */
    public function handle(UserLogin $event)
    {
        info('do something1');
    }
}
复制代码

在两个监听器的 handle 方法中咱们打印一个日志来测试一下,如代码 handle 方法所示。测试

分发和触发事件

咱们在某个控制器的方法中来分发事件,也就是触发事件,看监听器是否正常工做。ui

就是一句话:

event(new UserLogin());
复制代码

而后咱们请求这个控制器,观察日志,发现打印了日志:

[2018-06-17 10:04:29] local.INFO: do something1 [2018-06-17 10:04:29] local.INFO: do something2

那么这个事件-监听机制就正常工做了。

队列异步处理

若是某个监听器须要执行的操做比较慢,能够放到消息队列进行异步处理。

好比把上面的 DoSomething1 改为须要放入队列的,只须要 implements ShoulQueue 接口。

class DoSomething1 implements ShouldQueue
复制代码

也能够指定队列驱动,以下代码。

/**
     * 任务应该发送到的队列的链接的名称
     *
     * @var string|null
     */
    public $connection = 'redis';
 
    /**
     * 任务应该发送到的队列的名称
     *
     * @var string|null
     */
    public $queue = 'listeners';
复制代码

咱们再次执行控制器方法。

日志里没有打印 do something1,只有 do something2,可是在 redis 队列里发现了一个名为 queues:default 的列表。

{"job":"Illuminate\\Events\\CallQueuedHandler@call","data":{"class":"App\\Listeners\\DoSomething1","method":"handle","data":"a:1:{i:0;O:20:\"App\\Events\\UserLogin\":1:{s:6:\"socket\";N;}}"},"id":"3D7VDUwueYGtUvsazicWsifwWQxnnLID","attempts":1}
复制代码

这个时候须要使用 php artisan queue:work 执行队列任务,才是真正执行 DoSomething1 这个监听器的 handle 方法。

参考连接

  • Laravel 5.5 事件系统(https://laravel-china.org/docs/laravel/5.5/events/1318)
  • Laravel 队列(https://laravel-china.org/docs/laravel/5.5/queues/1324)

(原文地址:https://blog.tanteng.me/2018/06/laravel-event/)

相关文章
相关标签/搜索