美文网首页
PHP EventBus 事件总线简单实现

PHP EventBus 事件总线简单实现

作者: 非常帅气的昵称吧 | 来源:发表于2021-09-09 18:26 被阅读0次

PHP EventBus主要用处

主要解决模块之间太过耦合, 模块无法横向扩展的问题. 举个栗子

现在有个图片上传的模块, 把图片保存到服务器本地

function upload() {
//保存图片到本地
}

现在要增加需求 图片保存之前要裁切压缩

// 引用图片处理相关库
function upload() {
// 保存图片到本地
// 图片裁切压缩
}

现在又要增加需求 需要把图片存储到七牛云上

// 引用图片处理相关库
// 引用七牛云相关库
function upload() {
// 保存图片到本地
// 图片裁切压缩
// 图片上传到七牛云
}

随着需求不断变更 这里的代码也会不断增加, 给开发调试带来很大不确定性

使用EventBus事件总线, 代码可以变成如下形式

function upload() {
// 保存图片到本地
// 广播事件
  EventBus::emit('image-upload')
}

图片处理模块接收到事件, 进行处理

// 引用图片处理相关库
EventBus::on('image-upload', function () {
  //裁切压缩图片
})

七牛云存储模块接收到事件, 进行处理

// 引用七牛云相关库
EventBus::on('image-upload', function () {
  //图片上传到七牛云
})

这样就降低了模块之间的耦合, 各个模块各司其职, 方便开发调试, 需求的变更也能很轻松处理, 只需要横向扩展其余模块来处理事件就行

下面就是EventBus的简单实现, 直接上代码

  1. EventOption.php
<?php
namespace eventbus;
/**EventBus项
 * Class EventOption
 * @package eventbus
 */
class EventOption {
    /** 执行方法
     * @var mixed
     */
    public $execute;
    /** 执行顺序
     * @var int|mixed
     */
    public $index = 0;

    public function __construct($data)
    {
        $this->execute = $data['execute'];
        $this->index = $data['index'];
    }
}

  1. EventBus.php
<?php
namespace eventbus;
/** EventBus 全局事件处理
 * Class EventBus
 * @package eventbus
 */
class EventBus {
    //创建静态私有的变量保存该类对象
    static private $instance;
    private $events = [];
    //防止使用new直接创建对象
    private function __construct(){}

    //防止使用clone克隆对象
    private function __clone(){}

    static public function getInstance()
    {
        //判断$instance是否是Singleton的对象,不是则创建
        if (!self::$instance instanceof self) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /** 注册事件
     * @param $key
     * @param EventOption $option
     */
    static public function on($key, EventOption $option) {
        $eventbus = EventBus::getInstance();
        if (!isset($eventbus->events[$key])) {
            $eventbus->events[$key] = [];
        }
        $op_index = $option->index;
        $added = false;
        foreach ($eventbus->events[$key] as $i => $item) {
            $index = $item->index;
            if ($op_index >= $index) {
                array_splice($eventbus->events[$key], $i, 0, [$option]);
                $added = true;
                break;
            }
        }
        if (!$added) {
            $eventbus->events[$key][] = $option;
        }
    }

    /** 触发事件
     * @param $key
     * @param mixed ...$args
     * @return array|null
     */
    static public function emit($key, ...$args) {
        $eventbus = EventBus::getInstance();
        if (!isset($eventbus->events[$key])) {
            return null;
        }
        $events = $eventbus->events[$key];
        $res = null;
        foreach ($events as $e) {
            $execute = $e->execute;
            $res = $execute(...$args);
        }
        return $res;
    }
}

使用:

  1. 注册事件
<?php
use \eventbus\EventBus;
use \eventbus\EventOption;

EventBus::on('aaa-oss-test', new EventOption([
    'execute'=>function ($data) {
        return 'oss test !!!!!!';
    },
    'index'=>1
]));

  1. 触发事件
$res = EventBus::emit('aaa-oss-test', [
            'file'=>0,
            'filesize'=>1
        ]);

整体思想借鉴了javascript和andrord的EventBus, 一般常用的注销事件 off 和 单次执行事件 once 因为没有想到具体使用场景 所以没有实现, 具体可以随意扩展

这就是PHP EventBus 事件总线的简单实现, 大家有什么好的思路和建议, 可以留言交流

相关文章

网友评论

      本文标题:PHP EventBus 事件总线简单实现

      本文链接:https://www.haomeiwen.com/subject/meqwwltx.html