thinkphp 一个文件怎么调用另一个文件中的define()_ThinkPHP自动加载Loader源码分析...

想了很久终于要开始系列文章的编写了,期望是写出提升和面试都可以搞定的系列文章。当你看到本文时,如果你发现咔咔没有编写到的面试热点问题或者技术难点,期待评论区指出,一起完善。

前言

目前在整理PHP进阶路线图,如有好的建议咔咔会第一时间进行收录。

一、自动加载loader源码分析

1-1 学习目标

  • 类的自动加载
  • 类自动加载的俩种方式
  • spl_autoload_register必须会使用
  • 实现自定义文件的类的自动加载

1-2 Composer加载

4c5b48be539a879dff74e10125086a95.png
在这里插入图片描述

从上图咔咔给的解析图,在base.php中首先加载了loader类,接着调用了register这个方法。

2295831c87cba7bbb445f6a58f0f0bb5.png来到thinkphp\library\think\Loader.php有一个register的方法,在这个方法里边,我们先学习第一个知识点spl_autoload_register()聊聊spl_autoload_register前世今生和简单使用,直接点击即可查看。

紧接着就是项目的根路径和composer的路径。

ac2b3d01895a080353b198c55a6a4f63.png
在这里插入图片描述

从这里开始就是在加载composer文件,过程也是很简单

  • 1.判断composer是否为目录
  • 2.判断路径下面的autoload_static.php是否为文件
  • 3.引入autoload_static.php文件
  • 4.返回所有已经声明的所有类  数组返回
  • 5.获取最后一个类ComposerStaticInit30742487e00917c888d89ba216f165b9
  • 6.判断ComposerStaticInit30742487e00917c888d89ba216f165b9中是否存在数组中的数据

2085823f373776002f0b32da110782f1.png接着可以去vendor\composer\autoload_static.php文件中可以看到这俩个属性

30fb1522da3a742a376bb23b80e493b2.png这里有一段代码估计有一部分同学会在这里绕一下self::${$attr} = $composerClass::${$attr};,这里的$attr就是'prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'这些数据,外层在加一个$符号。

从而在ComposerStaticInit30742487e00917c888d89ba216f165b9这个类中直接获取对应的属性值,也就是上图的俩个属性值。

d087e44ffaa9f193a3fb6a35bb0e0ef4.png
在这里插入图片描述

1-3 注册命名空间

文件还是thinkphp\library\think\Loader.phpregister方法

在这里注册了俩个命令空间,分别为think和traits。然后会进入到addNamespace这个方法中a0a564472cfa3f1f3875d5063cc55838.pngaddNamespace方法中,添加了Psr4空间

ad8599c7a9bb9975885ac11b3bfc767c.png接着来到addPsr4这个方法,会把这俩个命名空间都注册到ComposerStaticInit1e269472f484e157e90227b420ffca7a类的$prefixLengthsPsr4和$prefixDirsPsr4这俩个属性中

c546ddc6019fc1a97bd25920a3f2060e.png为了验证上面做一个断点调试,看到这些数据就应该清晰了,至于traits也是一样的注册方式。

截止到这里命名空间就注册完成了,接下来研究一下psr4命名空间是个什么东东。5027f05f608634f6642855e90222e6b3.png

1-4 Psr4是什么玩意

psr是简单的理解就是文件路径、自动加载对应类的相关规范、目前TP5.1使用的是psr4规范

此处的类是指class、接口、超类结构

一个完整的类需要一下结构\(\)*\

以下规范来源于PHP文档

  • 完整的类名必须要有一个顶级命名空间,被称为 "vendor namespace";

  • 完整的类名可以有一个或多个子命名空间;

  • 完整的类名必须有一个最终的类名;

  • 完整的类名中任意一部分中的下滑线都是没有特殊含义的;

  • 完整的类名可以由任意大小写字母组成;

  • 所有类名都必须是大小写敏感的。

以下是官方给的一个例子,这个psr规范能理解就尽量去理解它dbff743438e2f119425ea6491635bc46.png

1-5 加载类库映射文件

到这里,肯定会有一个疑问,这里怎么没有classmap.php这个文件。e547507515bb2d2afb0f42a90965ee9c.png不急不慌,先执行php think optimize:autoload把文件弄出来dfc98f5a434f85fd14c3f38e4b6169b9.png最终会走到addClassMap这个方法,在这个方法中,只是把classmap.php这个文件的数据赋值给$classMap 而已,没有什么其它的用法579e12bd01f060c90c23c357db0f4e2c.png

1-6 自动加载extend目录

extend这个目录用过TP框架的都多少用过的,在这个目录里边可以存放一下自定义的类库文件。

根据下图可以看到就是使用addAutoLoadDir这个方法进行加载的

365ca1d4b9927558a7a2788aa2dfefb3.png在方法中也仅仅是把extend的路径赋值给了$fallbackDirsPsr4这个属性。

de6c994d3973f66ff690c7ecadc7a08e.png截止到这里Loader::register();这部分就结束了,接着我们深入的看一下内部实现和实践案例。

在以上阅读源码中有四个属性,简单的整理一下

c2a4cb30cc9a220971929971d87bb77c.png
在这里插入图片描述

二、简说类的加载过程

b2552ce0c29bec26e5378d068de3e9dd.png
在这里插入图片描述

在刚刚开始解析这里的源码时就有一个函数spl_autoload_register

当需要使用的类没有被引入时,这个函数会在PHP报错前被触发,未定义的类名会被当作参数传入这里会直接去执行think\\Loader::autoload这个方法

3c05e4d12ae1387097c807eaa86ea78a.png经过断点第一个未加载的类就是think\Error

bc8e45ad54fc5aa8b836b13b3a772931.png为什么是think\Error呢!可以在回到thinkphp/base.php看一下,当自动加载完执行完成后第一个执行的类就是Error

6dcd4d7d1c99e95b8a4dea4b8ddbc6fe.png可以简单的做个测试,将这Error改为Kaka,进行打印一下,这时的类就改变为Kaka。到这里大家对这个类的自动加载机制就有一定的了解了。

当使用的类没有被引入时会把这个类当做参数传到thinkphp/library/think/Loader.phpautoload方法中。

47fb8896409a1ec42440d34fd84bde4c.png到这里在进行看一下autoload这个方法

f132662bb472a397f71cc1a53aa0b073.png先从findFile这个方法走,把未引入的类传入这个方法中,在findFile这个方法中会直接从classMap这个属性中直接把think\Error这个类映射的文件直接返回出来

534bdfa8b4cd574672e06fa62b4bb40e.png将think\Error这个类的完整路径返回给autoloadfile变量后,把win环境的大小写给判断了一次。

然后直接使用include引入文件即可,直到返回。

直到这里就是一次完整的类的自动加载解析。

6d9dd42f1c497f22dd6032fd70954332.png虽然到这里结束了,但是还是得在提一点就是$classMap这个属性,这个属性是基于文件classmap.php来到,这个文件的生成也是需要执行命令php think optimize:autoload生成的。

当没有生成这个文件时程序是如何执行的呢!

之前的所有流程都是一样的,只有在findFile这里不一样,接下来进行简单的梳理一下。

这时代码肯定不会走classMap

35aaa9c3c128a0ddac03298be61a90d1.png先获取think\Error文件

7b4173789927999f96185ddacb540432.png然后经过Composer自动加载中的俩个属性进行获取命名空间,在把think\Error.php文件进行拼接

70f155e5a1a501c2b244316a8f2dd775.png最终返回的结果也是D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\thinkphp\library\think\Error.php这个文件。

这里的代码需要好好的阅读一下。

类的自动加载到这里就是完全结束了。

三、自定义文件如何实现类的自动加载

先创建一个文件夹kaka

86e496b79d2727566f52f105088d3d95.png这时在控制器index中引入文件Kaka.php

fada44e43c2b211e2623e61bbfb7576c.png直接进行访问,这时这个类肯定会报错,那么我们应该怎么操作一下,就可以直接访问呢!

3ff0092865541381c4ce47c80dcf7149.png
在这里插入图片描述

这个时候就体现到源码的重要性了,还记得在自动加载的register函数中,加载过extend目录

56a3bceeaebf140b60bb61eca1bc2380.png
在这里插入图片描述

这时在加一个kaka这个目录,直接进行访问一下

6f163b3e241ea02237bab54cdb90aad1.png没毛病,直接就出来了。一切OK8407fca1353f5773eef13efce874ab56.png在这里在聊一下关于extent的加载方式

在之前聊注册自动加载类库目录只是说明了一下只是把路径存到了$fallbackDirsPsr4属性,没有细细说,接下来就是说明这些了。

阅读源码只能是实现那然后查看那

65a38cff3b83f5857b48d7500dcbac04.png
在这里插入图片描述

只要是定义的类都会进去到autoload进行自动加载

同样也会进入到findFile这个方法

d6b8def010003a30e11740473df38bd8.png在findFile这个方法中可以看到这段代码,这个属性是不是很熟悉,就是自动加载extend目录时添加到$fallbackDirsPsr4属性的。

c9e950356392a3351b7db09c6f20264f.png当在findFile中打印参数class时看一下数据

很清楚地可以看到test\Kaka这个类

838371f2b86e1d2ec34a819af61938b8.png03592e49857d9fb1dc9465ee8d602320.png此时在打印一下这个$fallbackDirsPsr4属性里边返回的file

86d876aadfdbf210c241959832248113.png然后就是使用__include_file来直接includeD:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\kaka\test\Kaka.php我们定义的文件。

以上的这个自定义文件如何实现类的自动加载,并且也就是extend的加载方式

四、总结

关于类自动加载的所有流程就完成了,如有错误之处可以在评论区哦!

1dd7f44486a5f61706e5a8d91e984784.gif

坚持学习、坚持写博、坚持分享是咔咔从业以来一直所秉持的信念。希望在偌大互联网中咔咔的文章能带给你一丝丝帮助。我是咔咔,下期见。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值