您的位置:首页 > 编程语言 > PHP开发

【thinkphp3.x】ThinkPHP/Common/runtime.php文件分析

2012-09-06 14:22 459 查看
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

/**
* ThinkPHP 运行时文件 编译后不再加载
* @category Think
* @package Common
* @author liu21st <liu21st@gmail.com>
*/
//此文件只在第一次运行入口文件时会执行,如果不是第一次运行入口文件,则不会再执行此文件
//判断THNK_PATH是否已经被定义,如果没被定义,则终止程序
defined('THINK_PATH') or exit();
//判断当前php的版本是否大于5.2.0
if(version_compare(PHP_VERSION,'5.2.0','<')) die('require PHP > 5.2.0 !');

// 版本信息
define('THINK_VERSION', '3.1');

// 系统信息
if(version_compare(PHP_VERSION,'5.3.0','<')) {
set_magic_quotes_runtime(0);//是否自动在某些特殊字符前面加上反斜线
define('MAGIC_QUOTES_GPC',get_magic_quotes_gpc()?True:False);
}else{
define('MAGIC_QUOTES_GPC',True);
}
define('IS_CGI',substr(PHP_SAPI, 0,3)=='cgi' ? 1 : 0 );
define('IS_WIN',strstr(PHP_OS, 'WIN') ? 1 : 0 );
define('IS_CLI',PHP_SAPI=='cli'? 1 : 0);

// 项目名称,如果在入口文件中没有定义,则会将根目录作为项目的名称
defined('APP_NAME') or define('APP_NAME', basename(dirname($_SERVER['SCRIPT_FILENAME'])));
if(!IS_CLI) {//默认值为0
// 当前文件名
if(!defined('_PHP_FILE_')) {
if(IS_CGI) {
//CGI/FASTCGI模式下
$_temp = explode('.php',$_SERVER['PHP_SELF']);
define('_PHP_FILE_', rtrim(str_replace($_SERVER['HTTP_HOST'],'',$_temp[0].'.php'),'/'));
}else {
//定义当前执行脚本的名称,如:/index.php ,rtrim函数第二个参数:删除末端的'/'
define('_PHP_FILE_', rtrim($_SERVER['SCRIPT_NAME'],'/'));
}
}
if(!defined('__ROOT__')) {
// 网站URL根目录
if( strtoupper(APP_NAME) == strtoupper(basename(dirname(_PHP_FILE_))) ) {
$_root = dirname(dirname(_PHP_FILE_));
}else {//执行这里
$_root = dirname(_PHP_FILE_);
}
//定义网站的根目录
define('__ROOT__', (($_root=='/' || $_root=='\\')?'':$_root));
}

//支持的URL模式
define('URL_COMMON', 0); //普通模式
define('URL_PATHINFO', 1); //PATHINFO模式
define('URL_REWRITE', 2); //REWRITE模式
define('URL_COMPAT', 3); // 兼容模式
}

// 路径设置 可在入口文件中重新定义 所有路径常量都必须以/ 结尾
defined('CORE_PATH') or define('CORE_PATH', THINK_PATH.'Lib/'); // 系统核心类库目录
defined('EXTEND_PATH') or define('EXTEND_PATH', THINK_PATH.'Extend/'); // 系统扩展目录
defined('MODE_PATH') or define('MODE_PATH', EXTEND_PATH.'Mode/'); // 系统扩展目录/模式扩展目录
defined('ENGINE_PATH') or define('ENGINE_PATH', EXTEND_PATH.'Engine/'); // 系统扩展目录/引擎扩展目录
defined('VENDOR_PATH') or define('VENDOR_PATH', EXTEND_PATH.'Vendor/'); // 系统扩展目录/第三方类库目录
defined('LIBRARY_PATH') or define('LIBRARY_PATH', EXTEND_PATH.'Library/'); // 系统扩展目录/扩展类库目录
defined('COMMON_PATH') or define('COMMON_PATH', APP_PATH.'Common/'); // 项目公共目录
defined('LIB_PATH') or define('LIB_PATH', APP_PATH.'Lib/'); // 项目类库目录
defined('CONF_PATH') or define('CONF_PATH', APP_PATH.'Conf/'); // 项目配置目录
defined('LANG_PATH') or define('LANG_PATH', APP_PATH.'Lang/'); // 项目语言包目录
defined('TMPL_PATH') or define('TMPL_PATH', APP_PATH.'Tpl/'); // 项目模板目录
defined('HTML_PATH') or define('HTML_PATH', APP_PATH.'Html/'); // 项目静态目录
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH.'Logs/'); // 项目路径/runtime/项目日志目录
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH.'Temp/'); // 项目路径/runtime/项目缓存目录
defined('DATA_PATH') or define('DATA_PATH', RUNTIME_PATH.'Data/'); // 项目路径/runtime/项目数据目录
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH.'Cache/'); // 项目路径/runtime/项目模板缓存目录

// 为了方便导入第三方类库 设置Vendor目录到include_path
set_include_path(get_include_path() . PATH_SEPARATOR . VENDOR_PATH);//将第三方类库的路径加入到系统变量中

// 加载运行时所需要的文件 并负责自动目录生成
function load_runtime_file() {
// 加载系统基础函数库,D()函数、C()函数 、import()函数、vendor()函数、alias_import()、require_cache ()函数 、alias_import()函数 等都在此文件中定义
require THINK_PATH.'Common/common.php';//路径:ThinkPHP/Common/common.php
// 读取核心编译文件列表,//路径:ThinkPHP/Lib/Think.class.php
$list = array(
CORE_PATH.'Core/Think.class.php', // 这个文件很重要,主要用来读取配置文件,编译项目等等
CORE_PATH.'Core/ThinkException.class.php', // 异常处理类
CORE_PATH.'Core/Behavior.class.php', // 行为类
);
// 加载模式文件列表
foreach ($list as $key=>$file){
//require_cache()函数会将成功加载的文件置入静态数组变量$_importFiles[$filename]中
if(is_file($file)) require_cache($file);//加载核心编译文件:require_cache函数在common.php文件中定义
}

// 加载系统类库别名定义,一个别名对应一个核心类库,如:【别名】'Db'=>【核心类库】 CORE_PATH.'Core/Db.class.php',
/**
* 大概有如下几个别名
* 'Model' => CORE_PATH.'Core/Model.class.php',
* 'Db' => CORE_PATH.'Core/Db.class.php',
* 'Log' => CORE_PATH.'Core/Log.class.php',
* 'ThinkTemplate' => CORE_PATH.'Template/ThinkTemplate.class.php',
* 'TagLib' => CORE_PATH.'Template/TagLib.class.php',
* 'Cache' => CORE_PATH.'Core/Cache.class.php',
* 'Widget' => CORE_PATH.'Core/Widget.class.php',
* 'TagLibCx' => CORE_PATH.'Driver/TagLib/TagLibCx.class.php',
*/
alias_import(include THINK_PATH.'Conf/alias.php');

// 检查项目目录结构 如果不存在则自动创建
if(!is_dir(LIB_PATH)) {
// 如果不是目录,则创建项目目录结构
build_app_dir();
}elseif(!is_dir(CACHE_PATH)){
// 如果不是目录,则检查缓存目录,并创建缓存目录
check_runtime();
}elseif(APP_DEBUG){//在调试模式开启的情况下,在运行时会删除编译文件
// 调试模式切换删除编译缓存
if(is_file(RUNTIME_FILE)) unlink(RUNTIME_FILE);
}
}

// 检查缓存目录(Runtime) 如果不存在则自动创建
function check_runtime() {
if(!is_dir(RUNTIME_PATH)) {
//如果runtime目录不存在,则创建runtime目录
mkdir(RUNTIME_PATH);
}elseif(!is_writeable(RUNTIME_PATH)) {
//如果runtime目录不可写,则给出提示
header('Content-Type:text/html; charset=utf-8');
exit('目录 [ '.RUNTIME_PATH.' ] 不可写!');
}
mkdir(CACHE_PATH); // 创建项目模板缓存目录
if(!is_dir(LOG_PATH)) mkdir(LOG_PATH); // 日志目录
if(!is_dir(TEMP_PATH)) mkdir(TEMP_PATH); // 数据缓存目录
if(!is_dir(DATA_PATH)) mkdir(DATA_PATH); // 数据文件目录
return true;
}

// 在调试模式开启的情况下,不会执行此函数
// 创建编译缓存,此函数会将所有要编译的内容编译到~runtime.php文件中,此文件中没有php的结束标记
function build_runtime_cache($append='') {
// 生成编译文件
$defs = get_defined_constants(TRUE);//返回当前定义的所有常量组成的数组,可通过输出$defs查看效果
$content = '$GLOBALS[\'_beginTime\'] = microtime(TRUE);';
if(defined('RUNTIME_DEF_FILE')) { // 编译后的常量文件外部引入
file_put_contents(RUNTIME_DEF_FILE,'<?php '.array_define($defs['user']));
$content .= 'require \''.RUNTIME_DEF_FILE.'\';';
}else{
//array_define():根据数组生成常量的定义
$content .= array_define($defs['user']);//只有用户定义的常量
}

//第三方类库写入到环境变量中
$content .= 'set_include_path(get_include_path() . PATH_SEPARATOR . VENDOR_PATH);';

// 读取核心编译文件列表
$list = array(
THINK_PATH.'Common/common.php',
CORE_PATH.'Core/Think.class.php',
CORE_PATH.'Core/ThinkException.class.php',
CORE_PATH.'Core/Behavior.class.php',
);

foreach ($list as $file){
$content .= compile($file);//循环将这些文件中的内容拼接到$content后面【注意:每个文件的内容都去除了php标记】
}

// 系统行为扩展文件统一编译
if(C('APP_TAGS_ON')) { //这里值为false
$content .= build_tags_cache();
}

//包含别名文件,别名文件返回的数组数据赋值给$alias
$alias = include THINK_PATH.'Conf/alias.php';
$content .= 'alias_import('.var_export($alias,true).');';
// 编译框架默认语言包和配置参数
$content .= $append."\nL(".var_export(L(),true).");C(".var_export(C(),true).');G(\'loadTime\');Think::Start();';
file_put_contents(RUNTIME_FILE,strip_whitespace('<?php '.$content));
}

// 编译系统行为扩展类库
function build_tags_cache() {
$tags = C('extends');//跟ThinkPHP/Conf/tags.php文件有关,可参考
$content = '';
foreach ($tags as $tag=>$item){
foreach ($item as $key=>$name) {//也挺重要的,记得看一下下
$content .= is_int($key)?compile(CORE_PATH.'Behavior/'.$name.'Behavior.class.php'):compile($name);
}
}
return $content;
}

// 创建项目目录结构
function build_app_dir() {
// 没有创建项目目录的话自动创建
if(!is_dir(APP_PATH)) mkdir(APP_PATH,0777,true);
if(is_writeable(APP_PATH)) {
$dirs = array(
LIB_PATH,
RUNTIME_PATH,
CONF_PATH,
COMMON_PATH,
LANG_PATH,
CACHE_PATH,
TMPL_PATH, //项目的模板目录,即:Tpl
TMPL_PATH.C('DEFAULT_THEME').'/', //项目模板目录下默认风格目录
LOG_PATH,
TEMP_PATH,
DATA_PATH,
LIB_PATH.'Model/', //项目的模型目录
LIB_PATH.'Action/', //项目的控制器目录
LIB_PATH.'Behavior/',
LIB_PATH.'Widget/',
);
foreach ($dirs as $dir){
if(!is_dir($dir)) mkdir($dir,0777,true);//循环创建项目的各个目录
}
// 写入目录安全文件
build_dir_secure($dirs);
// 写入初始配置文件
if(!is_file(CONF_PATH.'config.php')) // 配置文件
file_put_contents(CONF_PATH.'config.php',"<?php\nreturn array(\n\t//'配置项'=>'配置值'\n);\n?>");
// 写入测试Action // 自动生成一个默认的控制器测试文件
if(!is_file(LIB_PATH.'Action/IndexAction.class.php'))
build_first_action(); //如果没有IndexAction.class.php文件,则生成一个测试控制器文件
}else{
header('Content-Type:text/html; charset=utf-8');
exit('项目目录不可写,目录无法自动生成!<BR>请使用项目生成器或者手动生成项目目录~');
}
}

// 创建测试Action
function build_first_action() { //默认控制器文件中的内容
$content = file_get_contents(THINK_PATH.'Tpl/default_index.tpl');
file_put_contents(LIB_PATH.'Action/IndexAction.class.php',$content);
}

// 生成目录安全文件
function build_dir_secure($dirs='') {
// 目录安全写入
if(defined('BUILD_DIR_SECURE') && BUILD_DIR_SECURE) {
defined('DIR_SECURE_FILENAME') or define('DIR_SECURE_FILENAME', 'index.html');
defined('DIR_SECURE_CONTENT') or define('DIR_SECURE_CONTENT', ' ');
// 自动写入目录安全文件
$content = DIR_SECURE_CONTENT;
$files = explode(',', DIR_SECURE_FILENAME);
foreach ($files as $filename){
foreach ($dirs as $dir)
file_put_contents($dir.$filename,$content);
}
}
}

// 加载运行时所需文件
load_runtime_file();
// 记录加载文件时间
G('loadTime');
// 执行入口
Think::Start(); //应用程序的初始化

如图所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  path file include build cache php