文章8
标签3
分类5

typecho 源码解析 - 初始化

入口文件

入口文件 index.php ,让我们跟着代码一探究竟。

/** 载入配置支持 */
if (!defined('__TYPECHO_ROOT_DIR__') && !@include_once 'config.inc.php') {
    file_exists('./install.php') ? header('Location: install.php') : print('Missing Config File');
    exit;
}

/** 初始化组件 */
Typecho_Widget::widget('Widget_Init');

/** 注册一个初始化插件 */
Typecho_Plugin::factory('index.php')->begin();

/** 开始路由分发 */
Typecho_Router::dispatch();

/** 注册一个结束插件 */
Typecho_Plugin::factory('index.php')->end();

index.php 文件流程:

  • 载入配置
    config.inc.php 文件如果存在就引入,不存在就判断 install.php 文件是否存在,存在就跳转到 install.php 安装程序,不存在就结束脚本的运行。这里略过安装的流程。在你安装程序的时候会生成 config.inc.php 文件,其主要工作是:定义程序常量 、设定包含路径、引入核心文件、执行程序初始化、设置数据库信息。

定义程序常量:根目录,插件目录,模版目录,后台目录。
设定包含路径:使用 set_include_path() 函数把插件目录、以及根目录下面的 var 目录加入包含路径。
引入核心文件:此时还没有注册自动加载,只能使用 require 引入。
执行程序初始化: Typecho_Common::init();
设置数据库信息:保存数据库连接信息并初始化数据对象。

Typecho_Common::init() 位于 var/Typecho/Common.php ,方法代码如下:

    public static function init()
    {
        /** 设置自动载入函数 */
        if (function_exists('spl_autoload_register')) {
            spl_autoload_register(array('Typecho_Common', '__autoLoad'));
        } else {
            function __autoLoad($className) {
                Typecho_Common::__autoLoad($className);
            }
        }

        /** 兼容php6 */
        if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
            $_GET = self::stripslashesDeep($_GET);
            $_POST = self::stripslashesDeep($_POST);
            $_COOKIE = self::stripslashesDeep($_COOKIE);

            reset($_GET);
            reset($_POST);
            reset($_COOKIE);
        }

        /** 设置异常截获函数 */
        set_exception_handler(array('Typecho_Common', 'exceptionHandle'));
    }

此方法主要用于注册自动加载,如果系统打开了 get_magic_quotes_gpc ,使用 stripslashesDeep 处理数据,去掉系统自动添加的反斜线。最后使用 Typecho_Common 类的 exceptionHandle 接管了系统异常的截获。

  • 系统(组件)初始化
    此时, conficg.inc.php 执行结束,控制权重新回到 index.php 。紧接着执行了 Typecho_Widget::widget('Widget_Init'); Typecho_Widget init 阶段注册的自动加载方法,把 _ \ 替换为 / 然后加上 .php ,这样类名就被映射到具体的文件了。

    public static function __autoLoad($className)
    {
        @include_once str_replace(array('\\', '_'), '/', $className) . '.php';
    }

Typecho_Widget 为例,系统将得到 Typecho/Widget.php ,由于系统的核心文件都在 var 下,在 confic.inc.php 设定包含路径的时候,已经把 var 加入到 include_path ,那么最终得到路径 var/Typecho/Widget.php
Widget 类是整个系统组件的基类(抽象类),它抽象出了几个不错的功能,会在系统的执行中不断用到。需要注意的是__call,__get,否则后续的调用会让你摸不到头脑。我们还是先回到 Typecho_Widget::widget() 方法吧。
widget方法其实是一个用以实例化对象的工厂方法。它接受一个类名,初始化Typecho_Request,Typecho_Response对象一并传入目标类名,执行目标类的构造方法和 execute 方法,然后将实例化的对象保存在 self::$_widgetPool[$alias] 数组中。

    public static function widget($alias, $params = NULL, $request = NULL, $enableResponse = true)
    {
        $parts = explode('@', $alias);
        $className = $parts[0];
        $alias = empty($parts[1]) ? $className : $parts[1];

        if (isset(self::$_widgetAlias[$className])) {
            $className = self::$_widgetAlias[$className];
        }

        if (!isset(self::$_widgetPool[$alias])) {
            /** 如果类不存在 */
            if (!class_exists($className)) {
                throw new Typecho_Widget_Exception($className);
            }

            /** 初始化request */
            if (!empty($request)) {
                $requestObject = new Typecho_Request();
                $requestObject->setParams($request);
            } else {
                $requestObject = Typecho_Request::getInstance();
            }

            /** 初始化response */
            $responseObject = $enableResponse ? Typecho_Response::getInstance()
            : Typecho_Widget_Helper_Empty::getInstance();

            /** 初始化组件 */
            $widget = new $className($requestObject, $responseObject, $params);

            $widget->execute();
            self::$_widgetPool[$alias] = $widget;
        }

        return self::$_widgetPool[$alias];
    }

Typecho_Widget::widget('Widget_Init'); 为例, Typecho_Widget widget 得到 Widget_Init ,实例化 var/Widget/Init.php Widget_Init 类后执行 execute 方法。该方法又调用了 $options = $this->widget('Widget_Options'); ,即自己又实例化了 Widget_Options 类, Widget_Options 读出了 user = 0 的系统变量并保存。 Widget_Init 进行了一系列的系统组件的初始化。包括但不限于Typecho_Cookie,Typecho_Router,Typecho_Plugin
Typecho_Widget::widget('Widget_Init')执行完毕后,系统初始化全部完成,开始真正的工作。
系统初始化完成后, index.php 后续的动作就是插件和路由。插件用于扩展系统功能,路由用于分发 url 到对应的文件执行业务逻辑,路由和插件详细功能和流程后续解析。

0 评论

评论已关闭