多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
自动加载的实现由`think\Loader`类 ## 自动加载 由于新版`ThinkPHP`完全采用了命名空间的特性,因此只需要给类库正确定义所在的命名空间,而命名空间的路径与类库文件的目录一致,那么就可以实现类的自动加载。 类库的自动加载检测顺序如下: 1、类库映射检测; 2、`PSR-4`自动加载检测; 3、`PSR-0`自动加载检测; 系统会按顺序检测,一旦检测生效的话,就会自动载入对应的类库文件。 ## 类库映射 遵循我们上面的命名空间定义规范的话,基本上可以完成类库的自动加载了,但是如果定义了较多的命名空间的话,效率会有所下降,所以,我们可以给常用的类库定义类库映射。命名类库映射相当于给类文件定义了一个别名,效率会比命名空间定位更高效,例如: ~~~ Loader::addClassMap('think\Log',LIB_PATH.'think\Log.php'); Loader::addClassMap('org\util\Array',LIB_PATH.'org\util\Array.php'); ~~~ 也可以利用`addClassMap`方法批量导入类库映射定义,例如: ~~~ $map = [ 'think\Log' => LIB_PATH.'think\Log.php', 'org\util\array'=> LIB_PATH.'org\util\Array.php' ]; Loader::addClassMap($map); ~~~ >[danger] 注意词代码放到common.php或者start.php文件中 # import()方法 >[info]语法: boolen import(class, baseUrl, ext) 实际执行的是:`Loader::import($class, $baseUrl, $ext)` 不推荐,此方法在5.1+被移除 | 参数 | 说明 | | --- | --- | | class | 必须,表示要导入的类库,具有命名空间的完整类。规则:目录分割符`DS`(/或\\)用`.`表示`.`用`#`表示 | | baseUrl | 可选,表示导入的基础路径,最好以目录分割符结尾 | | ext | 可选,表示导入的类库后缀,默认是 .php 。 | 当设置第二个参数且不是数组时,文件路径为`$baseUrl . $class . $ext;` ``` import('wechat-sdk.wechat', EXTEND_PATH, '.class.php');//引入 extend/wechat-sdk/wechat.class.php ``` 当没有设置第二个参数时,他会优先先查找符合PSR-4的这个类,不存在则查找当前模块下的这个类,还不存在则查找extend目录下的这个类,还不存在则查找其他模块下的此类,最后都没找到则返回false ``` //相对路径以网站根目录作为起始目录(这里偷懒不想新建其他目录,单纯加载extend里的文件的话,第二个参数是可以省略的) import('Test', '../extend'); //加载extend/user/Think.Test.php import('user.Think#Test', '../extend'); //在application\admin\controller\Index.php里定义加载当前模块下的文件如(aplication/admin/Test/Alipay.class.php) import('admin.Test.Alipay'); //或者 import('@.Test.Alipay'); ``` ### **vendor**()导入第三方类库 第一个参数中的.会解析成/ #会解析成. 加载vender文件夹下的文件还有一个方法省掉了路径 vendor($class, $ext = EXT) 实际调用`Loader::import($class, VENDOR_PATH, $ext);` 此函数在5.1被废除 ``` vendor('alipaycustom.AopEncrypt');//vendor/alipaycustom/AopEncrypt.php vendor('alipaycustom.alipaycustom#function');//vendor/alipaycustom/alipaycustom.function.php ``` ## Composer自动加载 5.0版本支持`Composer`安装的类库的自动加载,你可以直接按照`Composer`依赖库中的命名空间直接调用。 # **框架自动加载实现流程** ## 1\. 首先载入loader.php文件 然后使用loader::register()进行自动加载 方法名中包含以下 ![](https://img.kancloud.cn/06/9c/069c81b9d7f1a0660bdfbb915908ebbb_607x240.png) ## 2\. register()方法中 ## 第一步使用sql\_autoload\_register()自动加载类 然后获取到composer路径并导入componser文件下的的auto\_static.php文件 auto\_static.php文件中 定义了两个静态属性:prefixLengthPsr4和prefixDirsPsr4 ### prefixLengthPsr4 = array('t' => array('think\\componser' => 15),'a' => array('app'=>4)) ### prefixDirsPsr4 = array('think\\componser' =>array(0 => '/top/think/think-installer/src'),'app' =>array(0=>'/application')) ![](https://img.kancloud.cn/41/66/416695b83f385960caee526dd4bf72b1_708x537.png) 接下来 获取到所有的类名数组 然后从使用array\_pop()数组中弹出最后一个数组 ![](https://img.kancloud.cn/8d/de/8ddeecff1d4d5311974815a2e694a862_664x102.png) Composer\Autoload\ComposerStaticInit25f893be97b63d60134b87b9c2e8987a 使用property_exists() 检查遍历的字符串是否在 上面的弹出的类数组中 ![](https://img.kancloud.cn/f1/68/f16803f91dc30aea18618015cab2fc4a_923x201.png) ![](https://img.kancloud.cn/52/e2/52e2ab34900edb6d8881f3f9fd11be75_647x117.png) ![](https://img.kancloud.cn/08/b9/08b926a1b0ab85a7a737f9559fec4b28_1586x384.png) ## 3. 注册命名空间: ### 调用addNamespace() 参数是一个数组 参数是: array(2) { ["think"] =>string(57) "C:\Users\Administrator\Desktop\tp5\thinkphp\library\think" ["traits"] =>string(58) "C:\Users\Administrator\Desktop\tp5\thinkphp\library\traits"} ![](https://img.kancloud.cn/c3/bf/c3bfb5cb4ce5df86a80d4341042b4086_793x164.png) 在addNamespace中 又调用了addPsr4()参数是(上面的数组)并执行遍历由原来的二维数组 遍历成结果是一维数组 ![](https://img.kancloud.cn/af/fb/affb2acb1db9294781d04a8ed8011d04_971x342.png) addPsr4的方法作用是添加Psr4空间 因为传过来的参数不为空 所以走流程如下图所示: ![](https://img.kancloud.cn/b7/4a/b74a218645c740cc1ba5bf3962979c53_983x723.png) 因为没有找到这个值 所以走这个逻辑: ![](https://img.kancloud.cn/8e/58/8e58103b1a2f9d7d4441f82378f6f0da_815x299.png) 最后就添加到了Psr4空间中 ![](https://img.kancloud.cn/86/4f/864f7e41ba2754b5d75499aee5e17e8e_770x95.png) ![](https://img.kancloud.cn/d9/4b/d94bda38eabe5b4502f5bb442ba44553_763x476.png) ## 4. 加载类库映射文件 ### 调用addClassMap() 因为已经使用命令创建了类库映射文件 所以走箭头逻辑 ![](https://img.kancloud.cn/23/2f/232f1ea56c83e842e7ecd73562dba52d_492x61.png) ![](https://img.kancloud.cn/9d/eb/9debad8dfb3b6d0c6a82127d4cfadc9e_963x272.png) addClassMap()参数是刚生成的classMap.php文件内容 把类库文件内容 赋值给**self::$classMap** ### 5. 自动加载extend目录 ![](https://img.kancloud.cn/5f/80/5f8007a5381b56b730fef87c87c04ff1_638x105.png) 调用addAutoLoadDir()参数是extend的路径 在addAutoLoadDir中 把路径赋值给 **self::$fallbackDirsPsr4** ![](https://img.kancloud.cn/b3/41/b3415ad34df48e60eb2a8cffd55adf94_543x151.png) # -----------分割线----------- ## 注册错误和异常处理机制 ![](https://img.kancloud.cn/93/08/93083537e5a03fd028582ff3f80d1e0a_643x235.png) ### 1。Error类没有引用直接使用了 因此就出发了自动加载机制 就会自动调用Loader.php文件中的spl_autoload_register() ![](https://img.kancloud.cn/25/c1/25c1de8a3adc366fcabe298d2101968b_801x108.png) 就会调用autoload方法 ![](https://img.kancloud.cn/ad/72/ad7256f08f90f50d47d3a31c41f2e3e4_811x515.png) 在autoload中 先查看是否有别名 没别名就调用findFile()去类库文件查找 因为Error在类库文件中找到了 如果找不到就去Psr-4中寻找 然后去查找 PSR-4 fallback dirs 然后查找 PSR-0 然后查找 PSR-0 fallback dirs一路查找 如果还没找到 return **self::$classMap[$class]** = false; ![](https://img.kancloud.cn/bc/4a/bc4a0e9adf13d7353c45c13fea0f88be_779x520.png)