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的简单实现, 直接上代码
- 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'];
}
}
- 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;
}
}
使用:
- 注册事件
<?php
use \eventbus\EventBus;
use \eventbus\EventOption;
EventBus::on('aaa-oss-test', new EventOption([
'execute'=>function ($data) {
return 'oss test !!!!!!';
},
'index'=>1
]));
- 触发事件
$res = EventBus::emit('aaa-oss-test', [
'file'=>0,
'filesize'=>1
]);
整体思想借鉴了javascript和andrord的EventBus, 一般常用的注销事件 off 和 单次执行事件 once 因为没有想到具体使用场景 所以没有实现, 具体可以随意扩展
这就是PHP EventBus 事件总线的简单实现, 大家有什么好的思路和建议, 可以留言交流