ThinkPHP执行流程
时间:2010-05-02 来源:octans
1. 入口文件index.php
用户对url的访问首先被定位到http://<serverIp>/<appName>/index.php, 这里的入口文件index.php做三件事情:1.1, 1.2, 1.31.1 定义或载入全局变量
常见的有APP_NAME(项目名称), APP_PATH(项目路径), THINK_PATH(ThinkPHP框架路径); 我研究的是ThinkSNS1.6,它除了用ThinkPHP的全局变量比如THINK_MODE, 又加入了自己定义的一些全局变量,如SITE_PATH, SITE_URL, 注意到ThinkSNS定义了自己的模式ThinkSNS,
define('THINK_MODE','ThinkSNS'); |
关于ThinkPHP的模式扩展,在ThinkPHP2.0完全开发手册6.10模式扩展章节中有介绍,总的思想是通过模式扩展使得开发者可以定制自己需要使用的ThinkPHP底层框架核心,不必拘泥于ThinkPHP默认的标准模式。
1.2 加载框架入口文件ThinkPHP.php
入口文件通常是ThinkPHP.php,
require(THINK_PATH."/ThinkPHP.php"); |
而ThinkSNS定义了自己的入口文件ThinkSNS.php,不过总体的思想是一样的。 在这个框架入口文件,做下面的事情:
1.2.1 记录开始运行时间
$GLOBALS['_beginTime'] = microtime(TRUE); |
1.2.2 检测THINK_PATH,APP_NAME, APP_PATH
// ThinkPHP系统目录定义 |
1.2.3 检测项目编译缓存目录定义,没有则取项目的Temp目录
1.2.4 加载常量定义文件defines.php和公共函数文件functions.php
require THINK_PATH.'/Common/defines.php'; ... $runtime[] = THINK_PATH.'/Common/functions.php'; // 系统函数 |
1.2.5 加载核心基类
// 核心基类必须加载 |
1.2.6 加载核心编译文件
核心编译文件列表由文件core.php给出;可以自定制,放在CONFIG_PATH下;或者可以根据扩展模式放在THINK_MODE下;或者使用默认的THINK_PATH.'/Common/core.php'
// 读取核心编译文件列表
// 加载项目自定义的核心编译文件列表
THINK_PATH.'/Mode/'.strtolower(THINK_MODE).'.php'; |
默认的THINK_PATH.'/Common/core.php'的内容为
// 系统默认的核心列表文件 |
这样就加载了系统核心类库(包括App、Action、Model、View、ThinkException、Log)
1.2.7 生成核心编译缓存~runtime.php
如果没有定义NO_CACHE_RUNTIME, 则把上面步骤中加载的文件统一写到~runtime.php中,下次就可以直接调用核心编译缓存~runtime.php,无需再一一加载
// 生成核心编译缓存 去掉文件空白以减少大小 $compile = defined('RUNTIME_ALLINONE'); $content = compile(THINK_PATH.'/Common/defines.php',$compile); $content .= compile(defined('PATH_DEFINE_FILE')? PATH_DEFINE_FILE : THINK_PATH.'/Common/paths.php',$compile); foreach ($runtime as $file){ $content .= compile($file,$compile); } if(defined('STRIP_RUNTIME_SPACE') && STRIP_RUNTIME_SPACE == false ) { file_put_contents(RUNTIME_PATH.'~runtime.php','<?php'.$content); }else{ file_put_contents(RUNTIME_PATH.'~runtime.php',strip_whitespace('<?php'.$content)); } unset($content); } |
1.2.8 记录加载文件时间 $GLOBALS['_loadTime']
// 记录加载文件时间 |
1.3 执行应用,实例化App类
//实例化一个网站应用实例 |
在调用$App->run()时,具体做的事情,可看ThinkPHP\Lib\Think\Core\App.class.php里的public function run(),
/** |
那么接着看$this->init()做什么事情,根据下面的代码,看到 首先如果编译后的项目文件~app.php存在则直接加载它,如果不存在则调用build函数来生成~app.php; 之后通过define('MODULE_NAME',$this->getModule())和define('ACTION_NAME', $this->getAction())将模块和动作的名字放入全局变量
/** |
$this->init()执行完后,就完成了定义MODULE_NAME和ACTION_NAME,接着执行 $this->exec(),
/** |
根据上面代码, 首先创建Action控制器实例$module = A(MODULE_NAME), 其中function A()是在文件functions.php里的,它负责实例化对应的Action的class,它的部分代码如下,它根据MODULE_NAME来加载对应的Ation Class的文件,之后通过$action = new $className()进行实例化.
if('@'===$appName) { |
后记:由于看得文档时ThinkPHP2.0的,而所有的代码都是ThinkSNS1.6(使用的是ThinkPHP1.6)的,所以有些地方并不是很准确,但大体思想和步骤是一致的。