0x01 注册自动加载
在tp5中,从base.php
载入框架,第一件事就是实现自动加载。
首先,载入Loader
类
thinkphp\base.php
1 | require think; |
thinkphp\library\think\Loader.php
1 | // 注册自动加载机制 |
Composer自动加载支持
首先自动加载的是composer里的内容,composer的内容默认在vendor中。
他会去找其中的autoload_static.php
这里边有两个数组:
- $prefixLengthsPsr4:二维数组,先通过索引找命名空间,再映射到命名空间名的长度,以替换成路径。
- $prefixDirPsr4:命名空间到他的路径位置索引
这里存在一个问题, autoload_Static.php
里的类名是随机的:这里存在一个问题, autoload_Static.php
里的类名是随机的:
1 | # 拿到类名后检查类中是否存在指定属性 |
我们通过composer
加载的组件都可以通过这里加载框架中有引用。
1 | // 注册命名空间定义 |
这里找到了thinkphp/library/
目录下的两个文件夹,是框架级的类库。将这两个路径以数组的形式传入addNamespace
方法
1 | // 注册命名空间 |
这里是数组,就解数组然后通过addPsr4
这个方法将该属性注册到之前composer
加载的类库中。与其合并在$prefixLengthsPsr4
和$prefixDirPsr4
当中。
类库映射文件以及extend目录
- 类库映射关系,效率会比通过命名空间定位更高[1]
1 | // 加载类库映射文件 |
通过addClassMap
方法来实现类别名的映射,类库映射文件通过php think optimiz:autoload
命令在runtime
目录下生成。
1 | // 注册classmap |
将$class
都导入到了self::$classMap
的静态属性中。
接下来,加载extend
目录,这个目录下通常编写一些用户的基础类库,为了上层应用能加载到他。
1 | // 自动加载extend目录 |
0x02 使用流程
在base.php
中注册自动加载完成后开始注册错误和异常处理机制Error::register();
这个类不存在,激活spl_autoload_register
调用autoload
方法传入think\Error
:
1 | // 自动加载 |
这里主要是调用了self::findFile
这个方法, 这里会查找类库映射找到
1 | think/Error = /Applications/MAMP/htdocs/learn_tp5/learn_tp5/thinkphp/library//think/Error.php |
通过这条映射将该文件加载。如果没找到就会向后找注册Psr4属性(classMap->prefix->fallback)。再比如把runtime
下的类库映射文件classmap.php
删除,就会触发 查找 PSR-4
这一段:
如果我们开发了一个类库,放入到extends
文件夹下,如:
1 | //extend/mytools/sayHi.php |
在控制器中即可加载:
1 |
|
0x03 原理
这一部分涉及了spl_autoload_register
,命名空间
以及Psr4
的知识可参考[2]