日期:2014-05-16  浏览次数:20387 次

ThinkPHP框架引导类分析

该类文件在:ThinkPHP/Library/Think/Think.class.php

       该类可以说是ThinkPHP框架最为核心的类库,负责诸多配置加载,注册核心系统扩展(自动加载类库、异常处理、错误处理等),管理和维护类实例、别名映射,可以一说是一个框架的工厂(该类有些许面向对象弊端,比如:违背了面向对象单一职责,其负责功能复杂,关联类库和文件较多,有动一牵百的忧虑)。类中遇到的函数会在该类分析之后彻底分析,所涉及的其它类库会专门讲解。

一、类结构 

namespace Think;//定义命名空间
class Think {
    private static $_map      = array();//类库别名映射
    private static $_instance = array();//保存类实例(这么说也不合理,等会分析该功能时具体说明)
    static public function start() {}//应用程序初始化
    static public function addMap($class, $map=''){}// 注册classmap
    static public function getMap($class=''){}// 获取classmap
    public static function autoload($class) {}//类库自动加载
    static public function instance($class,$method='') {}//取得对象实例 支持调用类的静态方法
    static public function appException($e) {}//自定义异常处理
    static public function appError($errno, $errstr, $errfile, $errline) {}//自定义错误处理
    static public function fatalError() {} // 致命错误捕获
    static public function halt($error) {}//错误输出
    static public function trace($value='[think]',$label='',$level='DEBUG',$record=false) {}//添加和获取页面Trace记录
}

二、应用程序初始化start()方法分析,该方法包含一套错误和异常处理机制,非常受用。该方法作为ThinkPHP框架的引导接口,实现错误、异常处理,配置加载,别名映射,行为注册,包含运行缓存的生成,网站应用目录检测,自动类库加载行为注册。

/**
     * 应用程序初始化
     * @access public
     * @return void
     */
    static public function start() {
    	//使用spl标准库中提供__autoload()函数的默认实现,比__autoload()效率更高,更加灵活
    	//一下可以使用spl_autoload_register(array('Think\Think','autoload'));
    	//建议使用spl_autoload_register(__NAMESPACE__.'\Think::autoload');实现
    	//一下所有注册方式均可以使用上面3中形式传递参数
    	spl_autoload_register('Think\Think::autoload');
    	
    	//注册全局脚本"析构函数",使用该方式注册的函数,会在脚本结束前调用,大多数情况用来处理致命错误
    	register_shutdown_function('Think\Think::fatalError');
    	//设置自定义错误处理函数,用于处理错误信息
    	set_error_handler('Think\Think::appError');
    	//设置未异常处理函数
    	set_exception_handler('Think\Think::appException');
    	//可以把register_shutdown_function(),set_error_handler(),set_error_handler()3个函数组合完成自定义、多元化的错误处理模块
    	
    	//根据STORAGE_TYPE的值设置分布式文件存储方案,Storage是一个工厂类,用于管理和维护分布式文件存储组件
    	//后面会详细讲解Storage类,并指出设计缺陷
    	Storage::connect(STORAGE_TYPE);
    	
    	//根据运行模式在运行缓存目录下生成编译缓存文件APP_MODE.'~runtime.php',从而减少IO开销
    	//下面会详细介绍生成缓存文件的方式
    	$runtimefile  = RUNTIME_PATH.APP_MODE.'~runtime.php';
    	
    	//如果不是在调试模式,并且编译缓存文件存在,直接加载编译缓存
    	if(!APP_DEBUG && Storage::has($runtimefile)){
    		Storage::load($runtimefile);
    	}else{
    		//判断编译缓存文件是否存在,存在就删除
    		if(Storage::has($runtimefile))
    			Storage::unlink($runtimefile);
    		
    		//预编译内容变量
    		$content =  '';
    		//判断是否存在运行模式配置文件,如果不存在就加载MODE_PATH.APP_MODE.'.php',运行模式配置文件会影响下列加载不同的类库和配置
    		//运行配置文件后期会详细讲解
    		$mode   =   include is_file(CONF_PATH.'core.php')?CONF_PATH.'core.php':MODE_PATH.APP_MODE.'.php';
    	
    		//以下所有配置项加载都会根据加载的先后顺序覆盖之前的配置项,一般都是先加载ThinkPHP默认配置,再加载应用配置
    		//core下标决定要加载的核心类和函数文件
    		foreach ($mode['core'] as $file){
    			if(is_file($file)) {
    				include $file;
    				//如果不是调试模式,则编译该文件内容并储存到预编译内容变量中
    				if(!APP_DEBUG) $content   .= compile($file);
    			}
    		}
    
    		//config下标决定要加载的核心配置文件
    		foreach ($mode['config'] as $key=>$file){
    			//判断下标是否为数字,如果不是就会把该配置文件中的配置项加载到对应的键下面,相当于给配置项增加一个纬度
    			is_numeric($key)?C(include $file):C($key,include $file);
    		}
    
    		//如果不是普通运行模式,则判断是否存在运行模式应用配置文件
    		if('common' != APP_MODE && is_file(CONF_PATH.'config_'.APP_MODE.'.php'))
    			C(include CONF_PATH.'config_'.APP_MODE.'.php');
    
    		//alias下标记录类库别名映射规则,ThinkPHP独创别名机制,用于提升自动加载的效率
    		if(isset($mode['alias'])){
    			//由这句代码可以看出alias规