文章8
标签3
分类5

typecho 源码解析-插件

在上一篇文章中,我们讲完了系统的初始化,这篇我们会深入讲解 typecho 的插件机制。

插件,通俗来讲,就是埋在特定地点的 hook,当系统执行到埋有 hook 的地方,它会找出对应的 hook function并一一执行(hook 可以理解为钩子、挂载点。 hook function 可以理解为需要触发的功能)。

插件初始化

系统在我们上一篇文章里面说的系统初始化Typecho_Widget::widget('Widget_Init')环节执行了插件初始化的任务,即Typecho_Plugin::init($options->plugins),该方法传递了一个参数$options->plugins。上篇我们有说到$options是一个包含了user = 0的所有系统配置。$options->plugins是该配置下的插件配置。让我们看下Typecho_Plugin::init($options->plugins)做了那些工作,直接贴代码。

    public static function init(array $plugins)
    {
        $plugins['activated'] = array_key_exists('activated', $plugins) ? $plugins['activated'] : array();
        $plugins['handles'] = array_key_exists('handles', $plugins) ? $plugins['handles'] : array();

        /** 初始化变量 */
        self::$_plugins = $plugins;
    }

该方法检查并设置$plugins参数后赋值给self::$_plugins = $plugins

挂载点

挂载点用于通知挂载到此点的事件可以执行了.

index.php文件的Typecho_Plugin::factory('index.php')->begin()就是一个挂载点(hook)。其实就是通知挂载到index.php的事件可以执行了。流程细节如下:

Typecho_Plugin::factory('index.php')返回了Typecho_Plugin的实例化对象,构造函数确定了唯一的句柄index.php,紧接着执行了该实例的begin方法,由于该方法不存在,调用魔术方法__call去执行所有挂载在该点的插件。

Typecho_Plugin::factory()源码:

    public static function factory($handle)
    {
        return isset(self::$_instances[$handle]) ? self::$_instances[$handle] :
        (self::$_instances[$handle] = new Typecho_Plugin($handle));
    }

__call源码如下:

    public function __call($component, $args)
    {
        $component = $this->_handle . ':' . $component;
        $last = count($args);
        $args[$last] = $last > 0 ? $args[0] : false;

        if (isset(self::$_plugins['handles'][$component])) {
            $args[$last] = NULL;
            $this->_signal = true;
            foreach (self::$_plugins['handles'][$component] as $callback) {
                $args[$last] = call_user_func_array($callback, $args);
            }
        }

        return $args[$last];
    }

关键点:

  • __call可以带参数
  • $callback是一个保存了类名和方法名的数组,用于call_user_func_array回调实现插件的功能(hook function)。

Typecho_Plugin::factory('index.php')->begin()执行完毕后,程序进入路由分发。

0 评论

评论已关闭