一、类的自动加载初始
框架的灵魂,类的自动加载
为什么说是框架灵魂呢,一般框架都会有类的自动加载,当引入文件很多的时候,就会需要用到。这一个也是很多人想去阅读源码时卡住的点
源码阅读
- 打开到入口文件
../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();
- 在
Loader.php
中的 也就是register
方法中使用了spl_autoload_register
, 这种自动注册的加载方式是很多框架都会有的,比如Yii
这些。每一个框架实现的第一步都是类的自动加载
// 注册系统自动加载
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和文档,如果有需要的可以
更多学习内容可以访问【对标大厂】精品PHP架构师教程目录大全,只要你能看完保证薪资上升一个台阶(持续更新)
以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的 PHP技术交流群