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