手撸php框架5.2--构建Component之类级别事件实现

1.首先,类级别的事件是在BaseEvent类中实现的,它的实现方式和对象级别的方式类似,不过换成了静态的属性和方法,数据结构多了className一层,在触发事件时,要考虑到父类或接口中绑定的事件

2.数据结构

$eventClassMap;
[
    'eventName1' => [
        'className1' => [
            'handler1',
            'handler2'
        ]
    ],
]

3.绑定事件

public static function bindClassEvent($className, $eventName, $eventHandler, $onData=[], $handlerSequence = -1)
{
    $className   = ltrim($className, '\\');
    $isEmpty     = isset(self::$classEventMap[$eventName]) && isset(self::$classEventMap[$eventName][$className]) ? false : true;
    $handlerList = $isEmpty ? [] : self::$classEventMap[$eventName][$className];
    $insertValue = [$eventHandler, $onData];
    self::$classEventMap[$eventName][$className] = Tank::appendElementByPosition($handlerList, $handlerSequence, $insertValue);
}

4.解除绑定

public static function unbindClassEvent($className, $eventName, $eventHandler = null)
{
    $result = false;
    $className = ltrim($className, '\\');

    if (empty(self::$classEventMap[$eventName]) || empty(self::$classEventMap[$eventName][$className])) {
        $result = false;
    } else if (is_null($eventHandler)) {
        unset(self::$classEventMap[$eventName][$className]);
        $result = true;
    } else {
        $tmpEventMap = self::$classEventMap[$eventName][$className];
        foreach ($tmpEventMap as $key => $value) {
            if ($eventHandler == $value[0]) {
                unset(self::$classEventMap[$eventName][$className][$key]);
                $result = true;
            }
        }
        if ($result) {
            self::$classEventMap[$eventName][$className] = array_values(self::$classEventMap[$eventName][$className]);
        }
    }

    return $result;
}

5.触发事件,注意父类中绑定的事件,注意在对象级别事件触发时也要触发类级别事件,我们在5.2最后提过这个。

public static function triggerClassEvent($className, $eventName, $eventObject = null)
{
    if (!empty(self::$classEventMap[$eventName])) {
        if (is_null($eventObject)) {
            $eventObject = new BaseEvent();
        }
        if (is_null($eventObject->sender)) {

            if (is_object($className)) {
                $eventObject->sender = $className;
                $className = get_class($className);
            } else {
                $className = ltrim($className, '\\');
            }
        }

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

        $classNames = array_merge(
            [$className],
            class_parents($className, true),
            class_implements($className, true)
        );

        foreach ($classNames as $eachClassName) {
            if (!empty(self::$classEventMap[$eventName][$eachClassName])) {
                foreach (self::$classEventMap[$eventName][$eachClassName] as $value) {
                    $currentHandler = $value[0];
                    $currentData = $value[1];
                    $eventObject->onData = $currentData;
                    call_user_func($currentHandler, $eventObject);
                    if ($eventObject->stopFlag) {
                        break 2;
                    }
                }
            }
        }
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值