一、类的自动加载初始
框架的灵魂,类的自动加载
为什么说是框架灵魂呢,一般框架都会有类的自动加载,当引入文件很多的时候,就会需要用到。这一个也是很多人想去阅读源码时卡住的点
源码阅读
- 打开到入口文件
../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 ?: 'thinkLoader::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 (
'thinkcomposer' => 15,),'a' =>
array (
'app' => 4,);
public static $prefixDirsPsr4 = array (
'thinkcomposer' =>
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 插件,命名空间是 thinktest

2、修改 autoload_static.php

3、这样即可直接使用

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


更多学习内容可以访问【对标大厂】精品PHP架构师教程目录大全,只要你能看完保证薪资上升一个台阶(持续更新)
以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的 PHP技术交流群 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|