<?php// +----------------------------------------------------------------------// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]// +----------------------------------------------------------------------// | Copyright (c) 2006-2014 http://thinkVeVb.com All rights reserved.// +----------------------------------------------------------------------// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )// +----------------------------------------------------------------------// | Author: liu21st <liu21st@gmail.com>// +----------------------------------------------------------------------namespace Think;/** * ThinkPHP 引导类 * 开始了 最后的攻坚了 */html' target='_blank'>class Think { // 类映射 private static $_map = array(); // 仓库 类型 // 实例化对象 private static $_instance = array(); // 实例化 的位置 /** * 应用程序初始化 * @access public * @return void */ static public function start() { // 开始 初始了 // 第一步:先注册 各种方式。 // 注册AUTOLOAD方法 spl_autoload_register('Think/Think::autoload'); // 注册 自动执行函数 // 设定错误和异常处理 // 异常关闭 register_shutdown_function('Think/Think::fatalError'); //.也就是说当我们的脚本执行完成或意外死掉导致PHP执行即将关闭时,我们的这个函数将会 被调用. // 错误 set_error_handler('Think/Think::appError'); // 设置 错误处理 方式 // 异常 set_exception_handler('Think/Think::appException');// 设置 异常处理 方式 // 初始化文件存储方式 第二步:文件存储 Storage::connect(STORAGE_TYPE); // 初始化文件 存储 // 第三步:缓存文件开始 $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 = include is_file(CONF_PATH.'core.php')?CONF_PATH.'core.php':MODE_PATH.APP_MODE.'.php';// 读取 配置 文件 // 加载核心文件 foreach ($mode['core'] as $file){ if(is_file($file)) { include $file; if(!APP_DEBUG) $content .= compile($file); } }// 文件加载 // 加载应用模式配置文件 foreach ($mode['config'] as $key=>$file){ is_numeric($key)?C(load_config($file)):C($key,load_config($file)); } // 读取当前应用模式对应的配置文件 if('common' != APP_MODE && is_file(CONF_PATH.'config_'.APP_MODE.CONF_EXT)) C(load_config(CONF_PATH.'config_'.APP_MODE.CONF_EXT)); // 加载模式别名定义 if(isset($mode['alias'])){ self::addMap(is_array($mode['alias'])?$mode['alias']:include $mode['alias']); } // 加载应用别名定义文件 if(is_file(CONF_PATH.'alias.php')) self::addMap(include CONF_PATH.'alias.php'); // 加载模式行为定义 if(isset($mode['tags'])) { Hook::import(is_array($mode['tags'])?$mode['tags']:include $mode['tags']); } // 加载应用行为定义 if(is_file(CONF_PATH.'tags.php')) // 允许应用增加开发模式配置定义 Hook::import(include CONF_PATH.'tags.php'); // 加载框架底层语言包 L(include THINK_PATH.'Lang/'.strtolower(C('DEFAULT_LANG')).'.php'); if(!APP_DEBUG){ $content .= "/nnamespace { Think//Think::addMap(".var_export(self::$_map,true).");"; $content .= "/nL(".var_export(L(),true).");/nC(".var_export(C(),true).');Think/Hook::import('.var_export(Hook::get(),true).');}'; Storage::put($runtimefile,strip_whitespace('<?php '.$content)); }else{ // 调试模式加载系统默认的配置文件 C(include THINK_PATH.'Conf/debug.php'); // 读取应用调试配置文件 if(is_file(CONF_PATH.'debug'.CONF_EXT)) C(include CONF_PATH.'debug'.CONF_EXT); } }// 加载各种 生成 文件 // 读取当前应用状态对应的配置文件 if(APP_STATUS && is_file(CONF_PATH.APP_STATUS.CONF_EXT)) C(include CONF_PATH.APP_STATUS.CONF_EXT); // 读取当前的配置,临时配置文件 // 设置系统时区 date_default_timezone_set(C('DEFAULT_TIMEZONE')); // 检查应用目录结构 如果不存在则自动创建 if(C('CHECK_APP_DIR')) { $module = defined('BIND_MODULE') ? BIND_MODULE : C('DEFAULT_MODULE'); if(!is_dir(APP_PATH.$module) || !is_dir(LOG_PATH)){ // 检测应用目录结构 Build::checkDir($module); } }// 创建 需要创建的文件 // 记录加载文件时间 G('loadTime'); // 运行应用 App::run(); // 开始运行 其它的代码了。 }// 初始化 开始 // 注册classmap static public function addMap($class, $map=''){ if(is_array($class)){ self::$_map = array_merge(self::$_map, $class); }else{ self::$_map[$class] = $map; } } // 这个 确实 是注册 classmap 开始 // 获取classmap static public function getMap($class=''){ if(''===$class){ return self::$_map; }elseif(isset(self::$_map[$class])){ return self::$_map[$class]; }else{ return null; } }// 获取了 里面的 东西了。 /** * 类库自动加载 * @param string $class 对象类名 * @return void * 类库依赖加载 */ public static function autoload($class) { // 检查是否存在映射 if(isset(self::$_map[$class])) { include self::$_map[$class]; // 这里是这样的 包含对应的类文件的加载。 }elseif(false !== strpos($class,'//')){ // 如果 不是 那种带有 命名空间的 里面 // echo strstr("Hello world!","world",true); 显示 hello $name = strstr($class, '//', true); //strstr(string,search,before_search) if(in_array($name,array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$name)){ // Library目录下面的命名空间自动定位 $path = LIB_PATH; // 在这里的 开始 路径的准备了。 }else{ // 检测自定义命名空间 否则就以模块为命名空间 $namespace = C('AUTOLOAD_NAMESPACE'); // 模块的 命名空间了 $path = isset($namespace[$name])? dirname($namespace[$name]).'/' : APP_PATH; }// 开始检测了 $filename = $path . str_replace('//', '/', $class) . EXT; // 终于找到了对应的 文件 位置 if(is_file($filename)) { // Win环境下面严格区分大小写 if (IS_WIN && false === strpos(str_replace('/', '//', realpath($filename)), $class . EXT)){ return ; } include $filename; // 包含文件 } }elseif (!C('APP_USE_NAMESPACE')) { // 'APP_USE_NAMESPACE' => true, // 应用类库是否使用命名空间 // 自动加载的类库层 foreach(explode(',',C('APP_AUTOLOAD_LAYER')) as $layer){ if(substr($class,-strlen($layer))==$layer){ if(require_cache(MODULE_PATH.$layer.'/'.$class.EXT)) { return ; } } }// 自动 加载文件 缓存文件 // 根据自动加载路径设置进行尝试搜索 foreach (explode(',',C('APP_AUTOLOAD_PATH')) as $path){ if(import($path.'.'.$class)) // 如果加载类成功则返回 return ; } } }// 总结:就是 根据 文件名 之类的 解析了 对应的 类。 /** * 取得对象实例 支持调用类的静态方法 * @param string $class 对象类名 * @param string $method 类的静态方法名 * @return object */ static public function instance($class,$method='') { // 这种就是实例了 $identify = $class.$method;// 连接了 if(!isset(self::$_instance[$identify])) { if(class_exists($class)){ $o = new $class(); if(!empty($method) && method_exists($o,$method)) self::$_instance[$identify] = call_user_func(array(&$o, $method)); else self::$_instance[$identify] = $o; } else self::halt(L('_CLASS_NOT_EXIST_').':'.$class); } return self::$_instance[$identify]; } // 总结:就是调用到实际里面的 method 里面的东西 /** * 自定义异常处理 * @access public * @param mixed $e 异常对象 */ static public function appException($e) { $error = array(); $error['message'] = $e->getMessage(); // 获取信息 $trace = $e->getTrace();// 获取错误信息 if('E'==$trace[0]['function']) {// 里面 开始 $error['file'] = $trace[0]['file']; $error['line'] = $trace[0]['line']; }else{// 对的 $error['file'] = $e->getFile(); //获取文件 $error['line'] = $e->getLine(); // 获取 line } $error['trace'] = $e->getTraceAsString(); // 弄成字符串 Log::record($error['message'],Log::ERR);// 日志记录 // 发送404信息 header('HTTP/1.1 404 Not Found'); header('Status:404 Not Found'); self::halt($error);// 异常开始 } /** * 自定义错误处理 * @access public * @param int $errno 错误类型 * @param string $errstr 错误信息 * @param string $errfile 错误文件 * @param int $errline 错误行数 * @return void */ static public function appError($errno, $errstr, $errfile, $errline) { switch ($errno) { case E_ERROR: case E_PARSE: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: ob_end_clean(); $errorStr = "$errstr ".$errfile." 第 $errline 行."; if(C('LOG_RECORD')) Log::write("[$errno] ".$errorStr,Log::ERR); self::halt($errorStr); break; default: $errorStr = "[$errno] $errstr ".$errfile." 第 $errline 行."; self::trace($errorStr,'','NOTIC'); break; } }// 总结: 记录 外加 报错 // 致命错误捕获 static public function fatalError() { Log::save(); if ($e = error_get_last()) { switch($e['type']){ case E_ERROR: case E_PARSE: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: ob_end_clean(); self::halt($e); break; } } }// 致命错误 /** * 错误输出 * @param mixed $error 错误 * @return void */ static public function halt($error) { $e = array();// 内容开始 if (APP_DEBUG || IS_CLI) { //调试模式下输出错误信息 if (!is_array($error)) { // 这里的还要分 字符串 或者是 数组 $trace = debug_backtrace(); $e['message'] = $error; $e['file'] = $trace[0]['file']; $e['line'] = $trace[0]['line']; ob_start(); debug_print_backtrace(); $e['trace'] = ob_get_clean(); } else { $e = $error; } if(IS_CLI){// 直接 就开始了 exit(iconv('UTF-8','gbk',$e['message']).PHP_EOL.'FILE: '.$e['file'].'('.$e['line'].')'.PHP_EOL.$e['trace']); } } else { //否则定向到错误页面 $error_page = C('ERROR_PAGE'); if (!empty($error_page)) { redirect($error_page);// 直接 跳转 } else { $message = is_array($error) ? $error['message'] : $error; $e['message'] = C('SHOW_ERROR_MSG')? $message : C('ERROR_MESSAGE'); } } // 包含异常页面模板 $exceptionFile = C('TMPL_EXCEPTION_FILE',null,THINK_PATH.'Tpl/think_exception.tpl'); include $exceptionFile;// 包含模版 并且退出 exit; } // 包含模版 并且退出 // 总结: 这里的 不能 /** * 添加和获取页面Trace记录 * @param string $value 变量 * @param string $label 标签 * @param string $level 日志级别(或者页面Trace的选项卡) * @param boolean $record 是否记录日志 * @return void|array */ static public function trace($value='[think]',$label='',$level='DEBUG',$record=false) { static $_trace = array();// 这里的 又是静态仓库了,在一次运行中,要跑这么多东西,好累啊! if('[think]' === $value){ // 获取trace信息 return $_trace;// 也就是 默认的 返回了 }else{ $info = ($label?$label.':':'').print_r($value,true); // 这种是输出 到字符串 $level = strtoupper($level);// 转换成为了 if((defined('IS_AJAX') && IS_AJAX) || !C('SHOW_PAGE_TRACE') || $record) { Log::record($info,$level,$record); // 记录日志 }else{ if(!isset($_trace[$level]) || count($_trace[$level])>C('TRACE_MAX_RECORD')) { $_trace[$level] = array(); } $_trace[$level][] = $info; } } }// 这个是 记录 信息的整理了}PHP编程
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
新闻热点
疑难解答