ѡ̳

 找回密码
 ע
搜索
查看: 135|回复: 0
打印 上一主题 下一主题

thinkphp的核心类thinkphp.class.php源码

[复制链接]

789

主题

1158

帖子

4197

积分

Ա

Rank: 9Rank: 9Rank: 9

积分
4197
跳转到指定楼层
¥
发表于 2017-11-12 16:38:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


源码
  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. namespace Think;
  12. /**
  13. * ThinkPHP 引导类
  14. */
  15. class Think {

  16.     // 类映射
  17.     private static $_map      = array();

  18.     // 实例化对象
  19.     private static $_instance = array();

  20.     /**
  21.      * 应用程序初始化
  22.      * @access public
  23.      * @return void
  24.      */
  25.     static public function start() {
  26.       // 注册AUTOLOAD方法
  27.       spl_autoload_register('Think\Think::autoload');      
  28.       // 设定错误和异常处理
  29.       register_shutdown_function('Think\Think::fatalError');
  30.       set_error_handler('Think\Think::appError');
  31.       set_exception_handler('Think\Think::appException');

  32.       // 初始化文件存储方式
  33.       Storage::connect(STORAGE_TYPE);

  34.       $runtimefile  = RUNTIME_PATH.APP_MODE.'~runtime.php';
  35.       if(!APP_DEBUG && Storage::has($runtimefile)){
  36.           Storage::load($runtimefile);
  37.       }else{
  38.           if(Storage::has($runtimefile))
  39.               Storage::unlink($runtimefile);
  40.           $content =  '';
  41.           // 读取应用模式
  42.           $mode   =   include is_file(CONF_PATH.'core.php')?CONF_PATH.'core.php':MODE_PATH.APP_MODE.'.php';
  43.           // 加载核心文件
  44.           foreach ($mode['core'] as $file){
  45.               if(is_file($file)) {
  46.                 include $file;
  47.                 if(!APP_DEBUG) $content   .= compile($file);
  48.               }
  49.           }

  50.           // 加载应用模式配置文件
  51.           foreach ($mode['config'] as $key=>$file){
  52.               is_numeric($key)?C(load_config($file)):C($key,load_config($file));
  53.           }

  54.           // 读取当前应用模式对应的配置文件
  55.           if('common' != APP_MODE && is_file(CONF_PATH.'config_'.APP_MODE.CONF_EXT))
  56.               C(load_config(CONF_PATH.'config_'.APP_MODE.CONF_EXT));  

  57.           // 加载模式别名定义
  58.           if(isset($mode['alias'])){
  59.               self::addMap(is_array($mode['alias'])?$mode['alias']:include $mode['alias']);
  60.           }

  61.           // 加载应用别名定义文件
  62.           if(is_file(CONF_PATH.'alias.php'))
  63.               self::addMap(include CONF_PATH.'alias.php');

  64.           // 加载模式行为定义
  65.           if(isset($mode['tags'])) {
  66.               Hook::import(is_array($mode['tags'])?$mode['tags']:include $mode['tags']);
  67.           }

  68.           // 加载应用行为定义
  69.           if(is_file(CONF_PATH.'tags.php'))
  70.               // 允许应用增加开发模式配置定义
  71.               Hook::import(include CONF_PATH.'tags.php');   

  72.           // 加载框架底层语言包
  73.           L(include THINK_PATH.'Lang/'.strtolower(C('DEFAULT_LANG')).'.php');

  74.           if(!APP_DEBUG){
  75.               $content  .=  "\nnamespace { Think\Think::addMap(".var_export(self::$_map,true).");";
  76.               $content  .=  "\nL(".var_export(L(),true).");\nC(".var_export(C(),true).');Think\Hook::import('.var_export(Hook::get(),true).');}';
  77.               Storage::put($runtimefile,strip_whitespace('<?php '.$content));
  78.           }else{
  79.             // 调试模式加载系统默认的配置文件
  80.             C(include THINK_PATH.'Conf/debug.php');
  81.             // 读取应用调试配置文件
  82.             if(is_file(CONF_PATH.'debug'.CONF_EXT))
  83.                 C(include CONF_PATH.'debug'.CONF_EXT);           
  84.           }
  85.       }

  86.       // 读取当前应用状态对应的配置文件
  87.       if(APP_STATUS && is_file(CONF_PATH.APP_STATUS.CONF_EXT))
  88.           C(include CONF_PATH.APP_STATUS.CONF_EXT);   

  89.       // 设置系统时区
  90.       date_default_timezone_set(C('DEFAULT_TIMEZONE'));

  91.       // 检查应用目录结构 如果不存在则自动创建
  92.       if(C('CHECK_APP_DIR')) {
  93.           $module     =   defined('BIND_MODULE') ? BIND_MODULE : C('DEFAULT_MODULE');
  94.           if(!is_dir(APP_PATH.$module) || !is_dir(LOG_PATH)){
  95.               // 检测应用目录结构
  96.               Build::checkDir($module);
  97.           }
  98.       }

  99.       // 记录加载文件时间
  100.       G('loadTime');
  101.       // 运行应用
  102.       App::run();
  103.     }

  104.     // 注册classmap
  105.     static public function addMap($class, $map=''){
  106.         if(is_array($class)){
  107.             self::$_map = array_merge(self::$_map, $class);
  108.         }else{
  109.             self::$_map[$class] = $map;
  110.         }        
  111.     }

  112.     // 获取classmap
  113.     static public function getMap($class=''){
  114.         if(''===$class){
  115.             return self::$_map;
  116.         }elseif(isset(self::$_map[$class])){
  117.             return self::$_map[$class];
  118.         }else{
  119.             return null;
  120.         }
  121.     }

  122.     /**
  123.      * 类库自动加载
  124.      * @param string $class 对象类名
  125.      * @return void
  126.      */
  127.     public static function autoload($class) {
  128.         // 检查是否存在映射
  129.         if(isset(self::$_map[$class])) {
  130.             include self::$_map[$class];
  131.         }elseif(false !== strpos($class,'\\')){
  132.           $name           =   strstr($class, '\\', true);
  133.           if(in_array($name,array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$name)){
  134.               // Library目录下面的命名空间自动定位
  135.               $path       =   LIB_PATH;
  136.           }else{
  137.               // 检测自定义命名空间 否则就以模块为命名空间
  138.               $namespace  =   C('AUTOLOAD_NAMESPACE');
  139.               $path       =   isset($namespace[$name])? dirname($namespace[$name]).'/' : APP_PATH;
  140.           }
  141.           $filename       =   $path . str_replace('\\', '/', $class) . EXT;
  142.           if(is_file($filename)) {
  143.               // Win环境下面严格区分大小写
  144.               if (IS_WIN && false === strpos(str_replace('/', '\\', realpath($filename)), $class . EXT)){
  145.                   return ;
  146.               }
  147.               include $filename;
  148.           }
  149.         }elseif (!C('APP_USE_NAMESPACE')) {
  150.             // 自动加载的类库层
  151.             foreach(explode(',',C('APP_AUTOLOAD_LAYER')) as $layer){
  152.                 if(substr($class,-strlen($layer))==$layer){
  153.                     if(require_cache(MODULE_PATH.$layer.'/'.$class.EXT)) {
  154.                         return ;
  155.                     }
  156.                 }            
  157.             }
  158.             // 根据自动加载路径设置进行尝试搜索
  159.             foreach (explode(',',C('APP_AUTOLOAD_PATH')) as $path){
  160.                 if(import($path.'.'.$class))
  161.                     // 如果加载类成功则返回
  162.                     return ;
  163.             }
  164.         }
  165.     }

  166.     /**
  167.      * 取得对象实例 支持调用类的静态方法
  168.      * @param string $class 对象类名
  169.      * @param string $method 类的静态方法名
  170.      * @return object
  171.      */
  172.     static public function instance($class,$method='') {
  173.         $identify   =   $class.$method;
  174.         if(!isset(self::$_instance[$identify])) {
  175.             if(class_exists($class)){
  176.                 $o = new $class();
  177.                 if(!empty($method) && method_exists($o,$method))
  178.                     self::$_instance[$identify] = call_user_func(array(&$o, $method));
  179.                 else
  180.                     self::$_instance[$identify] = $o;
  181.             }
  182.             else
  183.                 self::halt(L('_CLASS_NOT_EXIST_').':'.$class);
  184.         }
  185.         return self::$_instance[$identify];
  186.     }

  187.     /**
  188.      * 自定义异常处理
  189.      * @access public
  190.      * @param mixed $e 异常对象
  191.      */
  192.     static public function appException($e) {
  193.         $error = array();
  194.         $error['message']   =   $e->getMessage();
  195.         $trace              =   $e->getTrace();
  196.         if('E'==$trace[0]['function']) {
  197.             $error['file']  =   $trace[0]['file'];
  198.             $error['line']  =   $trace[0]['line'];
  199.         }else{
  200.             $error['file']  =   $e->getFile();
  201.             $error['line']  =   $e->getLine();
  202.         }
  203.         $error['trace']     =   $e->getTraceAsString();
  204.         Log::record($error['message'],Log::ERR);
  205.         // 发送404信息
  206.         header('HTTP/1.1 404 Not Found');
  207.         header('Status:404 Not Found');
  208.         self::halt($error);
  209.     }

  210.     /**
  211.      * 自定义错误处理
  212.      * @access public
  213.      * @param int $errno 错误类型
  214.      * @param string $errstr 错误信息
  215.      * @param string $errfile 错误文件
  216.      * @param int $errline 错误行数
  217.      * @return void
  218.      */
  219.     static public function appError($errno, $errstr, $errfile, $errline) {
  220.       switch ($errno) {
  221.           case E_ERROR:
  222.           case E_PARSE:
  223.           case E_CORE_ERROR:
  224.           case E_COMPILE_ERROR:
  225.           case E_USER_ERROR:
  226.             ob_end_clean();
  227.             $errorStr = "$errstr ".$errfile." 第 $errline 行.";
  228.             if(C('LOG_RECORD')) Log::write("[$errno] ".$errorStr,Log::ERR);
  229.             self::halt($errorStr);
  230.             break;
  231.           default:
  232.             $errorStr = "[$errno] $errstr ".$errfile." 第 $errline 行.";
  233.             self::trace($errorStr,'','NOTIC');
  234.             break;
  235.       }
  236.     }
  237.    
  238.     // 致命错误捕获
  239.     static public function fatalError() {
  240.         Log::save();
  241.         if ($e = error_get_last()) {
  242.             switch($e['type']){
  243.               case E_ERROR:
  244.               case E_PARSE:
  245.               case E_CORE_ERROR:
  246.               case E_COMPILE_ERROR:
  247.               case E_USER_ERROR:  
  248.                 ob_end_clean();
  249.                 self::halt($e);
  250.                 break;
  251.             }
  252.         }
  253.     }

  254.     /**
  255.      * 错误输出
  256.      * @param mixed $error 错误
  257.      * @return void
  258.      */
  259.     static public function halt($error) {
  260.         $e = array();
  261.         if (APP_DEBUG || IS_CLI) {
  262.             //调试模式下输出错误信息
  263.             if (!is_array($error)) {
  264.                 $trace          = debug_backtrace();
  265.                 $e['message']   = $error;
  266.                 $e['file']      = $trace[0]['file'];
  267.                 $e['line']      = $trace[0]['line'];
  268.                 ob_start();
  269.                 debug_print_backtrace();
  270.                 $e['trace']     = ob_get_clean();
  271.             } else {
  272.                 $e              = $error;
  273.             }
  274.             if(IS_CLI){
  275.                 exit(iconv('UTF-8','gbk',$e['message']).PHP_EOL.'FILE: '.$e['file'].'('.$e['line'].')'.PHP_EOL.$e['trace']);
  276.             }
  277.         } else {
  278.             //否则定向到错误页面
  279.             $error_page         = C('ERROR_PAGE');
  280.             if (!empty($error_page)) {
  281.                 redirect($error_page);
  282.             } else {
  283.                 $message        = is_array($error) ? $error['message'] : $error;
  284.                 $e['message']   = C('SHOW_ERROR_MSG')? $message : C('ERROR_MESSAGE');
  285.             }
  286.         }
  287.         // 包含异常页面模板
  288.         $exceptionFile =  C('TMPL_EXCEPTION_FILE',null,THINK_PATH.'Tpl/think_exception.tpl');
  289.         include $exceptionFile;
  290.         exit;
  291.     }

  292.     /**
  293.      * 添加和获取页面Trace记录
  294.      * @param string $value 变量
  295.      * @param string $label 标签
  296.      * @param string $level 日志级别(或者页面Trace的选项卡)
  297.      * @param boolean $record 是否记录日志
  298.      * @return void|array
  299.      */
  300.     static public function trace($value='[think]',$label='',$level='DEBUG',$record=false) {
  301.         static $_trace =  array();
  302.         if('[think]' === $value){ // 获取trace信息
  303.             return $_trace;
  304.         }else{
  305.             $info   =   ($label?$label.':':'').print_r($value,true);
  306.             $level  =   strtoupper($level);
  307.             
  308.             if((defined('IS_AJAX') && IS_AJAX) || !C('SHOW_PAGE_TRACE')  || $record) {
  309.                 Log::record($info,$level,$record);
  310.             }else{
  311.                 if(!isset($_trace[$level]) || count($_trace[$level])>C('TRACE_MAX_RECORD')) {
  312.                     $_trace[$level] =   array();
  313.                 }
  314.                 $_trace[$level][]   =   $info;
  315.             }
  316.         }
  317.     }
  318. }
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | ע

本版积分规则

QQ|Archiver|ֻ|С|ѡ̳

GMT+8, 2026-5-2 04:36 , Processed in 0.074979 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表
0.088s