牛骨文教育服务平台(让学习变的简单)
博文笔记

TP5代码学习笔记:Loader

创建时间:2016-03-28 投稿人: 浏览次数:4099

一.概述

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

1.注册系统的自动加载方法  hinkLoader::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. hinkLoader::addNamespaceAlias("org","kukiiu");

 

检查是否定义类库映射

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

["thinkApp"]=> string(45) "F:hwphpstudy hinkphplibrary hinkApp.php"

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

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

定义映射方法:

1. hinkLoader::addMap("test",APP_PATH."indexcontrollerTest.php");

dump(class_exists("test"));

2.mode/common.php的alias是不是添加到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的第一个前的值取出来:

如”appindexcontrollerIndex” 得到 $name=’app’ $class=’indexcontrollerIndex’

 

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:hwphpstudyapplication”这个路径,之后如果在使用这个路径下的某个类,如 命名空间为appmyclassTest的类,就会将前缀替换为F:hwphpstudyapplicationmyclassTest.php,从而加载该类文件。

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

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


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

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

hinkLoader::addNamespace("kukiiu","../extend/kukiiu/");

hinkLoader::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目录,然后定义一个mylibTest类( 类文件位于thinkphp/extend/mylib/Test.php),就可以直接调用new mylibTest();

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

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

 

其他函数:

 ...


参考资料:

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



声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。