如果有人读这篇文章并跟着做的话,希望你能使用支持函数跳转的编辑器,还要善用var_dump和exit,对着源码去调试着看。跟着入口文件读,执行到哪里你看到哪里,对于那些不能一眼看出来的配置,则要记录下来,可能一个比较简单的功能会写出很长的代码,这个时候难免会看到后面忘了前面。

  那么进入正题,从index.php文件可以看到入口文件只定义了几项常量作为配置,紧接着就引入了require './ThinkPHP/ThinkPHP.php';

  

 1 // 检测PHP环境
 2 if(version_compare(PHP_VERSION,'5.3.0','<'))  die('require PHP > 5.3.0 !');
 3 
 4 // 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false
 5 define('APP_DEBUG',True);
 6 
 7 // 定义应用目录
 8 define('APP_PATH','./Application/');
 9 
10 // 引入ThinkPHP入口文件
11 require './ThinkPHP/ThinkPHP.php';

 

  在ThinkpPHP文件依然比较简单,tp定义了一些常量配置项(defined函数的写法让之前在index入口文件里定义的配置项不会被重置)记录了运行时间和内存使用信息,进行了php版本的判断,以及cli命令行模式的判断。并在文件末尾再次引入了Think核心类,并进行了初始化。

  require CORE_PATH.'Think'.EXT;路径为ThinkPHP\Library\Think\Think.class.php

  这个think类就比较长了,一开始就定义了$_map  ,   $_instance两个数组,其中$_map作为映射数组使用,think类在会把核心模块的路劲存在这个数组里。$_instance则存储了系统运行时所实例化的对象

1     // 类映射
2     private static $_map      = array();
3 
4     // 实例化对象
5     private static $_instance = array();

  刚刚的入口文件执行了start方法来运行系统。这个start方法则一开始就通过spl_autoload_register方法注册了自动加载函数。(php本身有一些魔术方法,在执行某些方法,或变量时,如果它找不到这个方法或变量,就会执行相应的魔术方法,tp便是用自己的自动引入方法替换了该方法,达到不需要引入,直接new对象,系统便会自动引入该类文件的目的)

 

 1 static public function start() {
 2       // 注册AUTOLOAD方法
 3       spl_autoload_register('Think\Think::autoload');      
 4       // 设定错误和异常处理
 5       register_shutdown_function('Think\Think::fatalError');
 6       set_error_handler('Think\Think::appError');
 7       set_exception_handler('Think\Think::appException');
 8 
 9       // 初始化文件存储方式
10       Storage::connect(STORAGE_TYPE);
11       ················

  我们往下翻看,autoload方法传入了一个$class类名,然后便在类的$_map里检测是否存在该类的映射,如果有,则表明是系统核心模块直接通过存储的地址include引入;反之则会判断$class是否为带有命名空间的路径字符串,然后通过strstr函数分割字符串获得命名空间前缀,判断是否为tp系统定义的命名空间,然后便通过之前定义的常量来确定文件路径。同时判断是否为win环境,进行大小写的匹配,然后include引入;

 1     public static function autoload($class) {
 2         // 检查是否存在映射
 3         if(isset(self::$_map[$class])) {
 4             include self::$_map[$class];
 5         }elseif(false !== strpos($class,'\\')){
 6           $name           =   strstr($class, '\\', true);
 7           if(in_array($name,array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$name)){ 
 8               // Library目录下面的命名空间自动定位
 9               $path       =   LIB_PATH;
10           }else{
11               // 检测自定义命名空间 否则就以模块为命名空间
12               $namespace  =   C('AUTOLOAD_NAMESPACE');
13               $path       =   isset($namespace[$name])? dirname($namespace[$name]).'/' : APP_PATH;
14           }
15           $filename       =   $path . str_replace('\\', '/', $class) . EXT;
16           if(is_file($filename)) {
17               // Win环境下面严格区分大小写
18               if (IS_WIN && false === strpos(str_replace('/', '\\', realpath($filename)), $class . EXT)){
19                   return ;
20               }
21               include $filename;
22           }
23         }elseif (!C('APP_USE_NAMESPACE')) {
24             // 自动加载的类库层
25             foreach(explode(',',C('APP_AUTOLOAD_LAYER')) as $layer){
26                 if(substr($class,-strlen($layer))==$layer){
27                     if(require_cache(MODULE_PATH.$layer.'/'.$class.EXT)) {
28                         return ;
29                     }
30                 }            
31             }
32             // 根据自动加载路径设置进行尝试搜索
33             foreach (explode(',',C('APP_AUTOLOAD_PATH')) as $path){
34                 if(import($path.'.'.$class))
35                     // 如果加载类成功则返回
36                     return ;
37             }
38         }
39     }
autoload

相关文章:

  • 2018-02-11
  • 2022-12-23
  • 2018-04-24
  • 2021-10-29
  • 2022-12-23
  • 2021-04-24
  • 2021-07-10
  • 2021-05-30
猜你喜欢
  • 2019-02-18
  • 2018-01-29
  • 2021-09-08
  • 2018-07-31
  • 2021-08-02
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案