十七、逐行阅读Yii2.0.43源码_Yii框架文件Event.php

目录

一、属性

二、方法


Event类是所有事件类的基类。Event类继承BaseObject类。

一、属性

1.4个实例属性

  • $name 事件名称
  • $sender事件发送者
  • $handled指示事件是否被处理了,如果为true,后续的事件处理函数,不会被调用
  • $data绑定事件可以传递额外的数据

2.2个静态属性

  • $_events全局注册的p普通事件处理函数
  • $_eventWildcards全局注册的通配符事件处理函数

    // 事件名称
    public $name;


    //事件发送者
    public $sender;


    //指示事件是否被处理
    //$handled设置为true,后续的事件处理函数,不在被调用
    public $handled = false;


    //附加事件处理器时传入的数据
    //可以作为Component::on()的第三个参数使用
    public $data;


    //包含所有全局注册的事件处理程序
    private static $_events = [];


    //全局注册的通配符事件处理程序
    private static $_eventWildcards = [];

二、方法

1. on方法,绑定类级别事件

  •  通配符事件
  • 普通事件
  • $append为true,新的事件放入事件列表尾部,为false,插入到事件列表前面
    /**
     * 绑定事件
     */
    public static function on($class, $name, $handler, $data = null, $append = true)
    {
        $class = ltrim($class, '\\');

        //1. 通配符事件
        if (strpos($class, '*') !== false || strpos($name, '*') !== false) {
            if ($append || empty(self::$_eventWildcards[$name][$class])) {
                self::$_eventWildcards[$name][$class][] = [$handler, $data];
            } else {
                array_unshift(self::$_eventWildcards[$name][$class], [$handler, $data]);
            }
            return;
        }

        //2. 普通事件
        if ($append || empty(self::$_events[$name][$class])) {
            self::$_events[$name][$class][] = [$handler, $data];
        } else {
            array_unshift(self::$_events[$name][$class], [$handler, $data]);
        }
    }

2. off方法,解绑类级别事件

  • 事件不存在, 返回false
  • $handler为null, 删除整个事件列表
  • 普通事件,删除$handler处理函数
  • 通配符事件,删除$handler处理函数
    /**
     * 解绑事件
     */
    public static function off($class, $name, $handler = null)
    {
        $class = ltrim($class, '\\');
        
        //1. 事件不存在, 返回false
        if (empty(self::$_events[$name][$class]) && empty(self::$_eventWildcards[$name][$class])) {
            return false;
        }
        
        //2.$handler为null, 删除整个事件列表
        if ($handler === null) {
            unset(self::$_events[$name][$class]);
            unset(self::$_eventWildcards[$name][$class]);
            return true;
        }

        // 3. 普通事件,删除$handler处理函数
        if (isset(self::$_events[$name][$class])) {
            $removed = false;
            foreach (self::$_events[$name][$class] as $i => $event) {
                if ($event[0] === $handler) {
                    unset(self::$_events[$name][$class][$i]);
                    $removed = true;
                }
            }
            if ($removed) {
                self::$_events[$name][$class] = array_values(self::$_events[$name][$class]);
                return true;
            }
        }

        // 4. 通配符事件,删除$handler处理函数
        $removed = false;
        if (isset(self::$_eventWildcards[$name][$class])) {
            foreach (self::$_eventWildcards[$name][$class] as $i => $event) {
                if ($event[0] === $handler) {
                    unset(self::$_eventWildcards[$name][$class][$i]);
                    $removed = true;
                }
            }
            if ($removed) {
                self::$_eventWildcards[$name][$class] = array_values(self::$_eventWildcards[$name][$class]);
                // 移除列表为空的事件,以便减少不必要的正则检查
                if (empty(self::$_eventWildcards[$name][$class])) {
                    unset(self::$_eventWildcards[$name][$class]);
                    if (empty(self::$_eventWildcards[$name])) {
                        unset(self::$_eventWildcards[$name]);
                    }
                }
            }
        }

        return $removed;
    }

 3. offAll方法,清空所有事件

    /**
     * 清除注册的所有类级别事件
     */
    public static function offAll()
    {
        self::$_events = [];
        self::$_eventWildcards = [];
    }

4. hasHandlers方法,检查指定的类级别事件是否存在

    /**
     * 返回指定的类级别事件是否存在
     */
    public static function hasHandlers($class, $name)
    {
        //1. 为空,直接返回false
        if (empty(self::$_eventWildcards) && empty(self::$_events[$name])) {
            return false;
        }

        if (is_object($class)) {
            $class = get_class($class);
        } else {
            $class = ltrim($class, '\\');
        }

        // 类,父类,实现的接口列表
        $classes = array_merge(
            [$class],
            class_parents($class, true),
            class_implements($class, true)
        );

        // 普通事件
        foreach ($classes as $className) {
            if (!empty(self::$_events[$name][$className])) {
                return true;
            }
        }

        // 通配符事件
        foreach (self::$_eventWildcards as $nameWildcard => $classHandlers) {
            if (!StringHelper::matchWildcard($nameWildcard, $name, ['escape' => false])) {
                continue;
            }
            foreach ($classHandlers as $classWildcard => $handlers) {
                if (empty($handlers)) {
                    continue;
                }
                foreach ($classes as $className) {
                    if (StringHelper::matchWildcard($classWildcard, $className, ['escape' => false])) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

5.trigger方法,触发类级别事件

    /**
     * 触发事件
     */
    public static function trigger($class, $name, $event = null)
    {
        $wildcardEventHandlers = [];
        
        //查找和通配符匹配的
        foreach (self::$_eventWildcards as $nameWildcard => $classHandlers) {
            if (!StringHelper::matchWildcard($nameWildcard, $name)) {
                continue;
            }
            $wildcardEventHandlers = array_merge($wildcardEventHandlers, $classHandlers);
        }

        //为空,返回
        if (empty(self::$_events[$name]) && empty($wildcardEventHandlers)) {
            return;
        }

        if ($event === null) {
            $event = new static();
        }
        $event->handled = false;
        $event->name = $name;

        if (is_object($class)) {
            if ($event->sender === null) {
                $event->sender = $class;
            }
            $class = get_class($class);
        } else {
            $class = ltrim($class, '\\');
        }

        // 类,父类,实现的接口列表
        $classes = array_merge(
            [$class],
            class_parents($class, true),
            class_implements($class, true)
        );

        foreach ($classes as $class) {
            $eventHandlers = [];
            
            //查找匹配的事件
            foreach ($wildcardEventHandlers as $classWildcard => $handlers) {
                if (StringHelper::matchWildcard($classWildcard, $class, ['escape' => false])) {
                    $eventHandlers = array_merge($eventHandlers, $handlers);
                    unset($wildcardEventHandlers[$classWildcard]);
                }
            }

            //合并事件处理函数
            if (!empty(self::$_events[$name][$class])) {
                $eventHandlers = array_merge($eventHandlers, self::$_events[$name][$class]);
            }

            foreach ($eventHandlers as $handler) {
                $event->data = $handler[1];
                call_user_func($handler[0], $event);

                //$event->handled为true,忽略后续的事件处理函数的执行
                if ($event->handled) {
                    return;
                }
            }
        }
    }

总结:

阅读了6个属性和5个方法:

  • $name 事件名称
  • $sender事件发送者
  • $handled指示事件是否被处理了,如果为true,后续的事件处理函数,不会被调用
  • $data绑定事件可以传递额外的数据
  • $_events全局注册的p普通事件处理函数
  • $_eventWildcards全局注册的通配符事件处理函数
  • on,off,offAll,hasHandlers,trigger5个事件相关的方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值