一、类的自动加载初始
框架的灵魂,类的自动加载
为什么说是框架灵魂呢,一般框架都会有类的自动加载,当引入文件很多的时候,就会需要用到。这一个也是很多人想去阅读源码时卡住的点
源码阅读
- 打开到入口文件
../public/index.php会看到这一段代码,此代码加载了base.php的核心文件
// 加载基础文件 [ ../public/index.php]
require __DIR__ . '/../thinkphp/base.php';
- 在
base.php中载入了一个ThinkPHP团队自己封装的底层基础类库。这个类库就是需要我们深入了解的Loader类。在载入后立即调用了Loader的register,并且下一句做好了Error错误处理
// 载入Loader类 [ ../thinkphp/base.php]
require __DIR__ . '/library/think/Loader.php';
// 注册自动加载
Loader::register();
// 注册错误和异常处理机制
Error::register();
// 注册系统自动加载
spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
二、自动加载 spl_autoload_register 初识
spl_autoload_register 的简介
-
spl_autoload_register函数是实现自动加载未定义类功能的的重要方法 -
所谓的自动加载意思就是我们的
new一个类的时候必须先include或者require的类文件,如果没有include或者require,则会报错。 -
但是这样就必须在文件头部写上许多
include或者require文件,非常麻烦。 -
为了使得没有
include或者require类的时候也正常 new 一个类,所以有了自动加载的概念 -
也就是说
new一个类之前不用事先包含类文件也可以正常new,这样我们的文件头部就不用包含许多include(require)。这就是为什么说spl_autoload_register是框架灵魂。
spl_autoload_register 的三个参数
autoload_function 参数
这是一个函数 方法 名称,可以是 字符串 或者 数组 调用类方法使用。这个函数 方法 的功能就是,来把需要 new 的类文件包含 include(require) 进来,这样 的时 new 候就不会找不到文件。其实就是封装整个项目的 include 和 require 功能。
可以理解为当我们 new 一个类,并且这个类文件没有被包含时候就会执行这个 autoload_function 方法
throw 参数
此参数设置了 autoload_function 无法成功注册时, spl_autoload_register() 是否抛出异常。
prepend 参数
如果是 true,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。
栗子.1
如下:先举个错误的栗子,可以看到当我们直接 new 一个未包含 class类 文件时候会报错

栗子.2
如下:当使用 spl_autoload_register() 后当 new 一个未包含的类时候,会去执行 spl_autoload_register() 第一个参数函数名的函数,这个函数有一个参数就是需要 new 的类名,这个函数的功能就是把这个类给包含进来(类名和文件名一致),这样就实现了自动加载功能。

栗子.3
如下:当然我们也可以改成这样

三、Composer 自动加载
源码分析 (Loader.php)
-
先获取到定义好的所有类
get_declared_classes() -
拿到
Composer安装的类信息 -
将
../vendor/composer/autoload_static.php内信息放入变量内 -
打完收工,这里有疑问没关系,先接着看
/** 存在 ../vendor/composer/ Composer目录则加载 */
if (is_dir(self::$composerPath)) {
if (is_file(self::$composerPath . 'autoload_static.php')) {
/** 加载 ../vendor/composer/autoload_static.php */
require self::$composerPath . 'autoload_static.php';
/** 返回所有已经定义的类 */
$declaredClass = get_declared_classes();
/** 获取到最后一个类 */
$composerClass = array_pop($declaredClass);
/** 查看 Composer 已经安装的包 */
foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) {
/** 将一些设定好的数据放入到变量内 */
if (property_exists($composerClass, $attr)) {
self::${$attr} = $composerClass::${$attr};
}
}
} else {
self::registerComposerLoader(self::$composerPath);
}
}
源码分析 (autoload_static.php)
- 大家可以看到,在上面定义好的数组里面就存在这两个内容
prefixLengthsPsr4, prefixDirsPsr4,files Composer的加载是在autoload_static.php取到的映射关系- 以下是未安装任何包的源码
public static $prefixLengthsPsr4 = array (
't' =>
array (
'think\\composer\\' => 15,
),
'a' =>
array (
'app\\' => 4,
),
);
public static $prefixDirsPsr4 = array (
'think\\composer\\' =>
array (
0 => __DIR__ . '/..' . '/topthink/think-installer/src',
),
'app\\' =>
array (
0 => __DIR__ . '/../..' . '/application',
),
);
- 这个时候我使用
Composer安装上topthink的think-helper,内部的映射关系就会变成以下这样
安装命令
$ composer require topthink/think-helper

- 首先是多了一个
files值,这个是安装包的路径 prefixLengthsPsr4中t多了一个think\\=>6。这个的意思也挺简单think-helper的命名空间是think,加上\\就是 6 个字符 (\\中夹带转义)prefixDirsPsr4也一样相对与上一个做出一个路径映射- 好了,源码就这样很简单。讲的不算清楚还望见谅!!!
举个栗子
- 一般在多人项目当中,我们一般会将
vendor内的文件设置忽略。但是因为种种原因有很多人会出现有包文件但没有修改autoload_static.php。或者举例一个场景:比如 A 需要用到一个插件,使用Composer下载好了之后。这个时候同事 B 偷懒直接将其插件文件复制过来。但是不管什么操作就是报错。那如何将一个复制的包载入到自动加载内呢
1、比如这个时候我存在一个 think-test 插件,命名空间是 think\test

2、修改 autoload_static.php

3、这样即可直接使用

点关注,不迷路
好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才。之前说过,PHP方面的技术点很多,也是因为太多了,实在是写不过来,写过来了大家也不会看的太多,所以我这里把它整理成了PDF和文档,如果有需要的可以


以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的 PHP技术交流群