手撸php框架5.1--构建Component之对象级别事件实现

本文介绍了一个基于PHP的事件系统的设计方案,包括事件类BaseEvent的定义、组件类中事件的绑定与触发机制等核心内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.首先我们需要一个事件类BaseEvent,我们在实现对象级别事件用到它的地方是:在触发时把这个类的实例作为事件处理器的参数传递进去,在同一个事件中的多个事件处理器间,是共享这个实例的。
BaseEvent类的代码如下:

<?php
namespace tank\base;

class BaseEvent extends BaseObject
{
    public $eventName;

    public $sender;

    public $onData = [];

    public $stopFlag = false;
}

需要注意的是,在实现对象级别的事件时,我们需要的BaseEvent就只有这些。在实现类级别的事件时,会添加其他代码,我们到时候再说回。

2.在Component类中,我们需要一个保存已经绑定的事件的数据结构。
该数据结构是这么设计的:

$eventMap;
[
    'eventName1' => [
        'handler1',
        'handler2'
    ],

    'eventName2' => [
        'handler2',
        'handler3'
    ]
]

以数组的键作为事件名,数组值是事件处理器,事件处理器的执行是顺序执行的。

3.绑定事件的方法,参数有事件名,事件处理器,绑定时数据和事件处理器的运行次序

public function bindEvent($eventName, $eventHandler, $onData = [], $handlerSequence = -1)
{
    $handlerList = isset($this->eventMap[$eventName]) ? $this->eventMap[$eventName] : [];
    $insertValue = [$eventHandler, $onData];
    $this->eventMap[$eventName] = Tank::appendElementByPosition($handlerList, $handlerSequence, $insertValue);
}

4.解除事件绑定的方法

public function unbindEvent($eventName, $eventHandler = null)
{
    $result = false;
    if (empty($this->eventMap[$eventName])) {
        $result = false;
    } else if (is_null($eventHandler)) {
        unset($this->eventMap[$eventName]);
        $result = true;
    } else {
        $tmpEventMap = $this->eventMap[$eventName];
        foreach ($tmpEventMap as $key => $value) {
            if ($eventHandler == $value[0]) {
                unset($this->eventMap[$eventName][$key]);
                $result = true;
            }
        }
        if ($result) {
            $this->eventMap[$eventName] = array_values($this->eventMap[$eventName]);
        }
    }

    return $result;
}

5.触发事件的方法

public function triggerEvent($eventName, BaseEvent $eventObject = null)
{
    if (!empty($this->eventMap[$eventName])) {
        if (is_null($eventObject)) {
            $eventObject = new BaseEvent();
        }
        if (is_null($eventObject->sender)) {
            $eventObject->sender = $this;
        }

        $eventObject->stopFlag = false;
        $eventObject->eventName = $eventName;

        foreach ($this->eventMap[$eventName] as $value) {
            $currentHandler = $value[0];
            $currentData = $value[1];
            $eventObject->onData = $currentData;
            call_user_func($currentHandler, $eventObject);
            if ($eventObject->stopFlag) {
                break;
            }
        }
    }

    BaseEvent::triggerClassEvent($this, $eventName, $eventObject);
}

最后一行的是类级别事件的触发,现在可以不用管,下次我们再说回。

ok,今儿个先到这,欲知后事如何,且听下回分解……
github源码:https://github.com/2lovecode/tank

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值