入口文件
入口文件 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 评论
评论已关闭