Stay hungry, Stay foolish

0%

TP笔记3:runtime编译

build_runtime()在TP里的注释是“生成核心编译缓存”,位于框架的Common目录下的runtime.php文件中。这个文件包含了四个函数:

  • build_runtime
  • mkdirs 批量创建目录。
  • build_app_dir 创建项目目录结构:

项目目录下的Common、Conf、Lang、Lib、Runtime、Tpl这些目录 在Conf下写一配置文件(config.php) 在Lib/Action下写一测试Action(IndexAction.class.php):刚安装ThinkPHP后运行出的那个Hello World。

  • check_runtime 检查项目下的缓存目录(Runtime) ,不存在将自动创建。(备用轮胎)
在这个文件里最主要的就是build_runtime了。所谓的核心编译缓存,就是在Runtime目录下的~runtime.php文件。(在上一节的ThinkPHP公共文件里有对这个文件的判断,如果存在,就直接加载,而不会再次编译)。

那么这个文件里到底包含了哪些东西呢?接下来我打开了一个存在的~runtime.php文件查看一下里面的结构:

  • 系统定义文件:define一大堆东西,IS_WIN、_PHP_FILE_、LIB_DIR、CONFIG_PATH等
  • Tink公共函数库:牛逼点的如C、D、M、U等快捷函数,常用的如dump、import等
  • 系统基类Think
  • 系统异常基类ThinkException
  • 日志处理类Log
  • 应用程序类App
  • 控制器基类Action(抽象)
  • 视图输出类View
  • 导入别名定义:Model、Session等类的路径

哦,原来~runtime.php就相当于框架的“配置文件”,放的都是框架运行时所必须的一些内容。接下来再看一下build_runtime的代码,就相对来说好理解多了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 生成核心编译缓存
function build_runtime() {
// 加载常量定义文件
require THINK_PATH.'/Common/defines.php';
// 加载路径定义文件
require defined('PATH_DEFINE_FILE')?PATH_DEFINE_FILE:THINK_PATH.'/Common/paths.php';
// 定义核心编译的文件
$runtime[] = THINK_PATH.'/Common/functions.php'; // 系统函数
if(version_compare(PHP_VERSION,'5.2.0','<') ) // 加载兼容函数 $runtime[] = THINK_PATH.'/Common/compat.php'; // 核心基类必须加载 $runtime[] = THINK_PATH.'/Lib/Think/Core/Think.class.php'; // 读取核心编译文件列表 if(is_file(CONFIG_PATH.'core.php')) { // 加载项目自定义的核心编译文件列表 $list = include CONFIG_PATH.'core.php'; }else{ if(defined('THINK_MODE')) { // 根据设置的运行模式加载不同的核心编译文件 $list = include THINK_PATH.'/Mode/'.strtolower(THINK_MODE).'.php'; }else{ // 默认核心 $list = include THINK_PATH.'/Common/core.php'; } } $runtime = array_merge($runtime,$list); // 加载核心编译文件列表 foreach ($runtime as $key=>$file){
if(is_file($file)) require $file;
}
// 检查项目目录结构 如果不存在则自动创建
if(!is_dir(RUNTIME_PATH)) {
// 创建项目目录结构
build_app_dir();
}else{
// 检查缓存目录
check_runtime();
}
// 生成核心编译缓存 去掉文件空白以减少大小
if(!defined('NO_CACHE_RUNTIME')) {
$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);<br /--> }else{
file_put_contents(RUNTIME_PATH.'~runtime.php',strip_whitespace('<!--?php'.$content));<br /--> }
unset($content);
}
}

说一下这个函数的流程吧:

  1. 导入常量定义文件(defines.php)和路径定义文件(paths.php)。为什么先导入这两个,因为这两个是“系统定义文件”,接下来所用到的CONFIG_PATH等都来自于它们。这里在加载paths.php的时候有一个PATH_DEFINE_FILE常量的判断,搜索了整个框架也只有在这个函数里用到。难道在入口文件里可以自己定义paths文件的路径,手册里也没有相关介绍。

  2. 把系统函数functions.php、兼容函数compat.php(如果PHP小于5.2.0的话)、核心基类Think.class.php这几个文件的路径写到$runtime数组里。

  3. 把核心编译文件core.php的路径放到$list变量 里。同$runtime合并,并全部载入。

  4. 检查项目目录和缓存目录。

  5. 生成~runtime.php缓存文件。这里也有一个常量NO_CACHE_RUNTIME,这个常量也是放在入口文件里定义,如果定义了,就不会生成缓存文件。

生成缓存文件用到了一个compile()的函数,位于系统函数文件里:

1
2
3
4
5
6
7
8
9
10
function compile($filename,$runtime=false) {
$content = file_get_contents($filename);
if(true === $runtime)
// 替换预编译指令
$content = preg_replace('///[RUNTIME](.*?)//[/RUNTIME]/s','',$content);
$content = substr(trim($content),5);
if('?>' == substr($content,-2))
$content = substr($content,0,-2);
return $content;
}

这个函数里也没有多大的玄机,就是读取文件内容,做一些处理:替换预编译指令、去掉开头的结尾的PHP标识。

处理完成后返回到build_runtime()的最后两步:

  1. 判断是否去掉空格:STRIP_RUNTIME_SPACE;

  2. file_put_contents()生成~runtime.php。

到此为止。我们的项目的编译就进行了一半:框架系统文件的编译就完成了。

接下来就要进行项目文件的编译,以及启动项目了——App::run(),该你上台了。

据说打赏我的人,代码没有BUG