TP5代码学习笔记:Loader

Posted kukiius

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TP5代码学习笔记:Loader相关的知识,希望对你有一定的参考价值。

自动加载Loader

一.概述

系统会调用Loader::register()方法注册自动加载,在这一步完成后,所有符合规范的类库(包括Composer依赖加载的第三方类库)都将自动加载。
系统的自动加载由两个部分组成:

1.注册系统的自动加载方法 \think\Loader::autoload

2.注册Composer自动加载(符合Composer规范即可)

一个类库的自动加载检测顺序为:

1.是否定义类库映射;

2.Composer自动加载检测;

3.是否为注册的命名空间;

4.检测EXTEND_PATH目录下的扩展类库;

如果检测到以上任何一处,则按照PSR-4命名规范自动加载。

可以看到,定义类库映射的方式是最高效的。

 

二.autoload类

Loader::autoload($class); 中打印出$class,运行如下:

  技术分享技术分享技术分享

可见$class为带命名空间的类名。

 

检测命名空间别名:有没有自动加载

比如定义了一个类 kukiiu/Upload。给他定义一个命名空间别名org,这样我使用org/Upload类,就会用kukiiu/Upload类重新定义一个org/Upload类。

定义命名空间别名方法:

1.\think\Loader::addNamespaceAlias(‘org‘,‘kukiiu‘);

 

检查是否定义类库映射

打印出$map可看到里面的每项元素如下所示:

["think\App"]=> string(45) "F:\hwphp\study\thinkphp\library\think\App.php"

定义了映射后,在直接使用该类时就会去搜索定义给出的文件路径名,然后加载该文件。

mode/common.php中定义了很多常用的类映射。

定义映射方法:

1.\think\Loader::addMap(‘test‘,APP_PATH.‘index\controller\Test.php‘);

dump(class_exists(‘test‘));

2.mode/common.phpalias是不是添加到map中?

 

Composer自动加载

执行composer install后,会在thinkphp/vendor下创建依赖文件。

1.tp在初始化时解析vendor/composer下的自动加载机制Loader::registerComposerLoader()

a) 加载PSR-0规范的‘composer/autoload_namespaces.php’文件。

 技术分享

解析后得到 self::$prefixesPsr0为:

 技术分享

 

b) 加载PSR-4规范的‘composer/autoload_psr4.php‘文件。

 技术分享

解析后得到 $prefixLengthsPsr4为:

 技术分享

$prefixDirsPsr4为:

 技术分享

c) 加载类映射文件(跟tp的类映射相同):‘composer/autoload_classmap.php‘。

d) 直接加载类文件。。。‘composer/autoload_files.php‘

2.在查找类时使用Loader::findFileInComposer()查看是否是composer下的类。

有点复杂,以后再看!

命名空间自动加载

没设置类映射,基本都是通过这里加载的类。打印出进入命名空间自动加载的类看看:

 技术分享

 

// 解析命名空间

list($name, $class) = explode(‘\\‘, $class, 2);

$class的第一个\前的值取出来:

如”app\index\controller\Index” 得到 $name=’app’ $class=’index\controller\Index’

 

if (isset(self::$namespace[$name])) {

   // 注册的命名空间

   $path = self::$namespace[$name];

} elseif (is_dir(EXTEND_PATH . $name)) {

   // 扩展类库命名空间

   $path = EXTEND_PATH . $name . DS;

} else {

   return false;

}

$filename = $path . str_replace(‘\\‘, DS, $class) . EXT;

 

1.注册命名空间:

判断$name值在不在注册的$namespace中,这里的命名空间和概念命名空间不是同一个意思,容易搞混,这里注册的$namespace是一个标识,感觉叫命名空间前缀会好点,按PSR-0规范应该叫‘供应商vendor’,看mode/common.php可以看到,默认的一些$namespace定义:

 技术分享

Loader::auotload()中打印出来$namespace如下所示:

 技术分享

所以$namespace作用就是:将命名空间的第一个\前的值$class作为前缀,通过这个前缀找到它代表的路径。如app标识就代表了”F:\hwphp\study\application\”这个路径,之后如果在使用这个路径下的某个类,如 命名空间为\app\myclass\Test的类,就会将前缀替换为F:\hwphp\study\application\myclass\Test.php,从而加载该类文件。

例如:在tp框架里,每个模块都放在application下,而$namespace里有个’app’代表了这个路径,所以模块中的类只要命名空间符合tp规定的规范,就能够通过命名空间转为文件路径,如\app\index\controller\Index控制器,就能转换为”F:\hwphp\study\application\index\controller\Index.php”文件路径。

tp的命名空间自动加载类是基于PSR-4标准,定义的$namespacekey是命名空间前缀,value是类的基路径。在得到类的全名后:将命名空间前缀替换为基路径,将其余命名空间添加到其后,添加类名和后缀。和PSR-4不同的是,这里的命名空间前缀只有一层,免去了循环判断前缀的操作,(list($name, $class) = explode(‘\\‘, $class, 2);)。简易流程如下所示:

技术分享

技术分享

技术分享

手动注册命名空间(标志)方法:

1.在应用入口文件中添加下面的代码:

\think\Loader::addNamespace(‘kukiiu‘,‘../extend/kukiiu/‘);

\think\Loader::addNamespace([

     ‘kukiiu‘=> ‘../extend/‘kukiiu‘/‘,

     ‘org‘ => ‘../extend/org/‘,

]);

2.在应用的配置文件中添加配置,系统会在应用执行的时候自动注册。

‘root_namespace‘ => [

     ‘my‘  => ‘../application/extend/my/‘,

]

3.mode/common.php$namespace下增加。

 

 

2.扩展类库命名空间:

thinkphp实现了自动注册命名空间(标识)机制,

把自己的类库包目录放入EXTEND_PATH目录(thinkphp/extend,可配置),就可以自动注册对应的命名空间(标识),

例如:在thinkphp/extend目录下面新增一个mylib目录,然后定义一个\mylib\Test类( 类文件位于thinkphp/extend/mylib/Test.php),就可以直接调用new \mylib\Test();

在入口文件定义常量EXTEND_PATH,可以自定义扩展类库目录。

可以看出,tp的扩展类是基于PSR-0的自动加载标准。

 

其他函数:

 ...


参考资料:

1.http://www.php-fig.org/psrPSR标准官网。








以上是关于TP5代码学习笔记:Loader的主要内容,如果未能解决你的问题,请参考以下文章

thinkphp学习笔记

webpackの学习笔记2

webpack学习笔记-2-file-loader 和 url-loader

webpack学习笔记

MIT 6.828 JOS学习笔记7. Lab 1 Part 2.2: The Boot Loader

MIT 6.828 JOS学习笔记4. Lab 1 Part 2.1: The Boot Loader