首页 > 语言 > PHP > 正文

thinkphp核心源码注释|Think.class.php

2024-05-05 00:04:36
字体:
来源:转载
供稿:网友
thinkphp核心源码注释|Think.class.php
  1. <?php 
  2. // +---------------------------------------------------------------------- 
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ] 
  4. // +---------------------------------------------------------------------- 
  5. // | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved. 
  6. // +---------------------------------------------------------------------- 
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 
  8. // +---------------------------------------------------------------------- 
  9. // | Author: liu21st <liu21st@gmail.com> 
  10. // +---------------------------------------------------------------------- 
  11.  
  12. namespace Think; 
  13. /** 
  14.  * ThinkPHP 引导类 
  15.  * 开始了 最后的攻坚了 
  16.  */ 
  17. class Think { 
  18.  
  19.     // 类映射 
  20.     private static $_map      = array(); // 仓库 类型 
  21.  
  22.     // 实例化对象 
  23.     private static $_instance = array(); // 实例化 的位置 
  24.  
  25.     /** 
  26.      * 应用程序初始化 
  27.      * @access public 
  28.      * @return void 
  29.      */ 
  30.     static public function start() { // 开始 初始了 
  31.         // 第一步:先注册 各种方式。 
  32.       // 注册AUTOLOAD方法 
  33.       spl_autoload_register('Think/Think::autoload');    // 注册 自动执行函数 
  34.       // 设定错误和异常处理 
  35.         // 异常关闭 
  36.       register_shutdown_function('Think/Think::fatalError'); //.也就是说当我们的脚本执行完成或意外死掉导致PHP执行即将关闭时,我们的这个函数将会 被调用. 
  37.       // 错误 
  38.         set_error_handler('Think/Think::appError'); // 设置 错误处理 方式 
  39.       // 异常 
  40.         set_exception_handler('Think/Think::appException');// 设置 异常处理 方式 
  41.  
  42.       // 初始化文件存储方式  第二步:文件存储 
  43.       Storage::connect(STORAGE_TYPE); // 初始化文件 存储 
  44.  
  45.         // 第三步:缓存文件开始 
  46.       $runtimefile  = RUNTIME_PATH.APP_MODE.'~runtime.php'// 初始化 生成文件 开始 
  47.       if(!APP_DEBUG && Storage::has($runtimefile)){ //非调试模式 
  48.           Storage::load($runtimefile); // 加载文件 
  49.       }else
  50.           // 调试模式 
  51.           if(Storage::has($runtimefile)) 
  52.               Storage::unlink($runtimefile);// 先删掉 
  53.           $content =  '';// 内容 准备 出来了 
  54.           // 读取应用模式 
  55.           $mode   =   include is_file(CONF_PATH.'core.php')?CONF_PATH.'core.php':MODE_PATH.APP_MODE.'.php';// 读取 配置 文件 
  56.           // 加载核心文件 
  57.           foreach ($mode['core'as $file){ 
  58.               if(is_file($file)) { 
  59.                 include $file
  60.                 if(!APP_DEBUG) $content   .= compile($file); 
  61.               } 
  62.           }// 文件加载 
  63.  
  64.           // 加载应用模式配置文件 
  65.           foreach ($mode['config'as $key=>$file){ 
  66.               is_numeric($key)?C(load_config($file)):C($key,load_config($file)); 
  67.           } 
  68.  
  69.           // 读取当前应用模式对应的配置文件 
  70.           if('common' != APP_MODE && is_file(CONF_PATH.'config_'.APP_MODE.CONF_EXT)) 
  71.               C(load_config(CONF_PATH.'config_'.APP_MODE.CONF_EXT));   
  72.  
  73.           // 加载模式别名定义 
  74.           if(isset($mode['alias'])){ 
  75.               self::addMap(is_array($mode['alias'])?$mode['alias']:include $mode['alias']); 
  76.           } 
  77.  
  78.           // 加载应用别名定义文件 
  79.           if(is_file(CONF_PATH.'alias.php')) 
  80.               self::addMap(include CONF_PATH.'alias.php'); 
  81.  
  82.           // 加载模式行为定义 
  83.           if(isset($mode['tags'])) { 
  84.               Hook::import(is_array($mode['tags'])?$mode['tags']:include $mode['tags']); 
  85.           } 
  86.  
  87.           // 加载应用行为定义 
  88.           if(is_file(CONF_PATH.'tags.php')) 
  89.               // 允许应用增加开发模式配置定义 
  90.               Hook::import(include CONF_PATH.'tags.php');    
  91.  
  92.           // 加载框架底层语言包 
  93.           L(include THINK_PATH.'Lang/'.strtolower(C('DEFAULT_LANG')).'.php'); 
  94.  
  95.           if(!APP_DEBUG){ 
  96.               $content  .=  "/nnamespace { Think//Think::addMap(".var_export(self::$_map,true).");"
  97.               $content  .=  "/nL(".var_export(L(),true).");/nC(".var_export(C(),true).');Think/Hook::import('.var_export(Hook::get(),true).');}'
  98.               Storage::put($runtimefile,strip_whitespace('<?php '.$content)); 
  99.           }else
  100.             // 调试模式加载系统默认的配置文件 
  101.             C(include THINK_PATH.'Conf/debug.php'); 
  102.             // 读取应用调试配置文件 
  103.             if(is_file(CONF_PATH.'debug'.CONF_EXT)) 
  104.                 C(include CONF_PATH.'debug'.CONF_EXT);            
  105.           } 
  106.       }// 加载各种 生成 文件 
  107.  
  108.       // 读取当前应用状态对应的配置文件 
  109.       if(APP_STATUS && is_file(CONF_PATH.APP_STATUS.CONF_EXT)) 
  110.           C(include CONF_PATH.APP_STATUS.CONF_EXT);   // 读取当前的配置,临时配置文件 
  111.  
  112.       // 设置系统时区 
  113.       date_default_timezone_set(C('DEFAULT_TIMEZONE')); 
  114.  
  115.       // 检查应用目录结构 如果不存在则自动创建 
  116.       if(C('CHECK_APP_DIR')) { 
  117.           $module     =   defined('BIND_MODULE') ? BIND_MODULE : C('DEFAULT_MODULE'); 
  118.           if(!is_dir(APP_PATH.$module) || !is_dir(LOG_PATH)){ 
  119.               // 检测应用目录结构 
  120.               Build::checkDir($module); 
  121.           } 
  122.       }// 创建 需要创建的文件 
  123.  
  124.       // 记录加载文件时间 
  125.       G('loadTime'); 
  126.       // 运行应用 
  127.       App::run(); // 开始运行 其它的代码了。 
  128.     }// 初始化 开始 
  129.  
  130.     // 注册classmap 
  131.     static public function addMap($class$map=''){ 
  132.         if(is_array($class)){ 
  133.             self::$_map = array_merge(self::$_map$class); 
  134.         }else
  135.             self::$_map[$class] = $map
  136.         }         
  137.     } // 这个 确实 是注册 classmap 开始 
  138.  
  139.     // 获取classmap 
  140.     static public function getMap($class=''){ 
  141.         if(''===$class){ 
  142.             return self::$_map
  143.         }elseif(isset(self::$_map[$class])){ 
  144.             return self::$_map[$class]; 
  145.         }else
  146.             return null; 
  147.         } 
  148.     }// 获取了 里面的  东西了。 
  149.  
  150.     /** 
  151.      * 类库自动加载 
  152.      * @param string $class 对象类名 
  153.      * @return void 
  154.      * 类库依赖加载 
  155.      */ 
  156.     public static function autoload($class) { 
  157.         // 检查是否存在映射 
  158.         if(isset(self::$_map[$class])) { 
  159.             include self::$_map[$class]; // 这里是这样的 包含对应的类文件的加载。 
  160.         }elseif(false !== strpos($class,'//')){ // 如果 不是 那种带有 命名空间的 里面 
  161.             // echo strstr("Hello world!","world",true); 显示 hello 
  162.           $name           =   strstr($class'//', true); //strstr(string,search,before_search) 
  163.           if(in_array($name,array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$name)){  
  164.               // Library目录下面的命名空间自动定位 
  165.               $path       =   LIB_PATH; // 在这里的 开始 路径的准备了。 
  166.           }else
  167.               // 检测自定义命名空间 否则就以模块为命名空间 
  168.               $namespace  =   C('AUTOLOAD_NAMESPACE'); // 模块的 命名空间了 
  169.               $path       =   isset($namespace[$name])? dirname($namespace[$name]).'/' : APP_PATH; 
  170.           }// 开始检测了 
  171.           $filename       =   $path . str_replace('//', '/', $class) . EXT; 
  172.             // 终于找到了对应的 文件 位置 
  173.           if(is_file($filename)) { 
  174.               // Win环境下面严格区分大小写 
  175.               if (IS_WIN && false === strpos(str_replace('/''//'realpath($filename)), $class . EXT)){ 
  176.                   return ; 
  177.               } 
  178.               include $filename// 包含文件 
  179.           } 
  180.         }elseif (!C('APP_USE_NAMESPACE')) { // 'APP_USE_NAMESPACE'     =>  true,    // 应用类库是否使用命名空间 
  181.             // 自动加载的类库层 
  182.             foreach(explode(',',C('APP_AUTOLOAD_LAYER')) as $layer){ 
  183.                 if(substr($class,-strlen($layer))==$layer){ 
  184.                     if(require_cache(MODULE_PATH.$layer.'/'.$class.EXT)) { 
  185.                         return ; 
  186.                     } 
  187.                 }             
  188.             }// 自动 加载文件 缓存文件 
  189.             // 根据自动加载路径设置进行尝试搜索 
  190.             foreach (explode(',',C('APP_AUTOLOAD_PATH')) as $path){ 
  191.                 if(import($path.'.'.$class)) 
  192.                     // 如果加载类成功则返回 
  193.                     return ; 
  194.             } 
  195.         } 
  196.     }// 总结:就是 根据 文件名 之类的 解析了 对应的 类。 
  197.  
  198.     /** 
  199.      * 取得对象实例 支持调用类的静态方法 
  200.      * @param string $class 对象类名 
  201.      * @param string $method 类的静态方法名 
  202.      * @return object 
  203.      */ 
  204.     static public function instance($class,$method='') { // 这种就是实例了 
  205.         $identify   =   $class.$method;// 连接了 
  206.         if(!isset(self::$_instance[$identify])) { 
  207.             if(class_exists($class)){ 
  208.                 $o = new $class(); 
  209.                 if(!emptyempty($method) && method_exists($o,$method)) 
  210.                     self::$_instance[$identify] = call_user_func(array(&$o$method)); 
  211.                 else 
  212.                     self::$_instance[$identify] = $o
  213.             } 
  214.             else 
  215.                 self::halt(L('_CLASS_NOT_EXIST_').':'.$class); 
  216.         } 
  217.         return self::$_instance[$identify]; 
  218.     } // 总结:就是调用到实际里面的 method 里面的东西 
  219.  
  220.     /** 
  221.      * 自定义异常处理 
  222.      * @access public 
  223.      * @param mixed $e 异常对象 
  224.      */ 
  225.     static public function appException($e) { 
  226.         $error = array(); 
  227.         $error['message']   =   $e->getMessage(); // 获取信息 
  228.         $trace              =   $e->getTrace();// 获取错误信息 
  229.         if('E'==$trace[0]['function']) {// 里面 开始 
  230.             $error['file']  =   $trace[0]['file']; 
  231.             $error['line']  =   $trace[0]['line']; 
  232.         }else{// 对的 
  233.             $error['file']  =   $e->getFile(); //获取文件 
  234.             $error['line']  =   $e->getLine(); // 获取 line 
  235.         } 
  236.         $error['trace']     =   $e->getTraceAsString(); // 弄成字符串 
  237.         Log::record($error['message'],Log::ERR);// 日志记录 
  238.         // 发送404信息 
  239.         header('HTTP/1.1 404 Not Found'); 
  240.         header('Status:404 Not Found'); 
  241.         self::halt($error);// 异常开始 
  242.     } 
  243.  
  244.     /** 
  245.      * 自定义错误处理 
  246.      * @access public 
  247.      * @param int $errno 错误类型 
  248.      * @param string $errstr 错误信息 
  249.      * @param string $errfile 错误文件 
  250.      * @param int $errline 错误行数 
  251.      * @return void 
  252.      */ 
  253.     static public function appError($errno$errstr$errfile$errline) { 
  254.       switch ($errno) { 
  255.           case E_ERROR: 
  256.           case E_PARSE: 
  257.           case E_CORE_ERROR: 
  258.           case E_COMPILE_ERROR: 
  259.           case E_USER_ERROR: 
  260.             ob_end_clean(); 
  261.             $errorStr = "$errstr ".$errfile." 第 $errline 行."
  262.             if(C('LOG_RECORD')) Log::write("[$errno] ".$errorStr,Log::ERR); 
  263.             self::halt($errorStr); 
  264.             break
  265.           default
  266.             $errorStr = "[$errno] $errstr ".$errfile." 第 $errline 行."
  267.             self::trace($errorStr,'','NOTIC'); 
  268.             break
  269.       } 
  270.     }// 总结: 记录 外加 报错 
  271.  
  272.     // 致命错误捕获 
  273.     static public function fatalError() { 
  274.         Log::save(); 
  275.         if ($e = error_get_last()) { 
  276.             switch($e['type']){ 
  277.               case E_ERROR: 
  278.               case E_PARSE: 
  279.               case E_CORE_ERROR: 
  280.               case E_COMPILE_ERROR: 
  281.               case E_USER_ERROR:   
  282.                 ob_end_clean(); 
  283.                 self::halt($e); 
  284.                 break
  285.             } 
  286.         } 
  287.     }// 致命错误 
  288.  
  289.     /** 
  290.      * 错误输出 
  291.      * @param mixed $error 错误 
  292.      * @return void 
  293.      */ 
  294.     static public function halt($error) { 
  295.         $e = array();// 内容开始 
  296.         if (APP_DEBUG || IS_CLI) { 
  297.             //调试模式下输出错误信息 
  298.             if (!is_array($error)) { // 这里的还要分 字符串  或者是 数组 
  299.                 $trace          = debug_backtrace(); 
  300.                 $e['message']   = $error
  301.                 $e['file']      = $trace[0]['file']; 
  302.                 $e['line']      = $trace[0]['line']; 
  303.                 ob_start(); 
  304.                 debug_print_backtrace(); 
  305.                 $e['trace']     = ob_get_clean(); 
  306.             } else { 
  307.                 $e              = $error
  308.             } 
  309.             if(IS_CLI){// 直接 就开始了 
  310.                 exit(iconv('UTF-8','gbk',$e['message']).PHP_EOL.'FILE: '.$e['file'].'('.$e['line'].')'.PHP_EOL.$e['trace']); 
  311.             } 
  312.         } else { 
  313.             //否则定向到错误页面 
  314.             $error_page         = C('ERROR_PAGE'); 
  315.             if (!emptyempty($error_page)) { 
  316.                 redirect($error_page);// 直接 跳转 
  317.             } else { 
  318.                 $message        = is_array($error) ? $error['message'] : $error
  319.                 $e['message']   = C('SHOW_ERROR_MSG')? $message : C('ERROR_MESSAGE'); 
  320.             } 
  321.         } 
  322.         // 包含异常页面模板 
  323.         $exceptionFile =  C('TMPL_EXCEPTION_FILE',null,THINK_PATH.'Tpl/think_exception.tpl'); 
  324.         include $exceptionFile;// 包含模版 并且退出 
  325.         exit
  326.     } // 包含模版 并且退出 
  327.     // 总结: 这里的 不能 
  328.  
  329.     /** 
  330.      * 添加和获取页面Trace记录 
  331.      * @param string $value 变量 
  332.      * @param string $label 标签 
  333.      * @param string $level 日志级别(或者页面Trace的选项卡) 
  334.      * @param boolean $record 是否记录日志 
  335.      * @return void|array 
  336.      */ 
  337.     static public function trace($value='[think]',$label='',$level='DEBUG',$record=false) { 
  338.         static $_trace =  array();// 这里的 又是静态仓库了,在一次运行中,要跑这么多东西,好累啊! 
  339.         if('[think]' === $value){ // 获取trace信息 
  340.             return $_trace;// 也就是 默认的 返回了 
  341.         }else
  342.             $info   =   ($label?$label.':':'').print_r($value,true); // 这种是输出 到字符串 
  343.             $level  =   strtoupper($level);// 转换成为了 
  344.  
  345.             if((defined('IS_AJAX') && IS_AJAX) || !C('SHOW_PAGE_TRACE')  || $record) { 
  346.                 Log::record($info,$level,$record); // 记录日志 
  347.             }else
  348.                 if(!isset($_trace[$level]) || count($_trace[$level])>C('TRACE_MAX_RECORD')) { 
  349.                     $_trace[$level] =   array(); 
  350.                 } 
  351.                 $_trace[$level][]   =   $info
  352.             } 
  353.         } 
  354.     }// 这个是 记录 信息的整理了 


注:相关教程知识阅读请移步到PHP教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选