微信小程序> Thinkphp5.1类自动加载机制

Thinkphp5.1类自动加载机制

浏览量:906 时间: 来源:littlexiaoshuishui

tp5.1类加载功能都封装到Loader类当中,所以我们主要分析这个类的主要功能。

1.几个重要属性

Loader::$prefixLengthsPsr4, 

Loader::$prefixDirsPsr4,

Loader:: $fallbackDirsPsr4,

Loader::$classMap

2.自动加载流程

2.1自动加载整个流程是通过Loader::register来实现的。

2.1.1.首先注册系统自动加载函数

所以自动加载函数就是Loader::autoload(), 注册后,当后面的代码有实例化不存在的类时,会直接调动这个方法。

2.1.2.然后 Composer自动加载支持

require composer目录(vendorcomposer)下的autoload_static.php文件,把autoload_static.php类的$prefixLengthsPsr4,$prefixDirsPsr4两个属性值赋值给Loader::$prefixLengthsPsr4, Loader::$prefixDirsPsr4属性。

当我们通过composer方式下载插件到项目的时候,composer命令会修改autoload_static.php中的$prefixLengthsPsr4,$prefixDirsPsr4这两个属性,指定该扩展的命名空间和对应目录。所以如果我们直接复制扩展到verdon目录的时候,需要修改这两个属性值,不然框架加载不到这个扩展。但是建议用composer命令来下载扩展,让命令自动帮我们修改。

这时Loader::$prefixLengthsPsr4, Loader::$prefixDirsPsr4就包含了composer下面的命名空间和对应的目录了。

 2.1.3.命名空间think,traits加载支持

// 注册命名空间定义        self::addNamespace([            'think'  = __DIR__,            'traits' = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'traits',        ]);

这段代码的意思就是在Loader::$prefixLengthsPsr4, Loader::$prefixDirsPsr4写入think, traits命名空间对应的目录。

2.1.4. 加载类库映射文件

// 加载类库映射文件 if (is_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php')) {    self::addClassMap(__include_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php'));}

这段代码判断runtimeclassmap.php文件是否存在,如果存在就把数据写入Loader::$classMap,这个其实就是用文件缓存类与类文件的映射关系。后面我们会讲到,代码实例化不存在的类时,会先include类文件,找类文件其实就是通过Loader的这几个属性来找的,如果存在$classMap,就直接找到类文件,提高了效率。

2.1.5.自动加载extend目录

 // 自动加载extend目录 self::addAutoLoadDir($rootPath . 'extend');

这段代码就是把extend目录路径写入到属性Loader:: $fallbackDirsPsr4

通过执行Loader::register()方法,可以确定vender目录(通过composer下载的扩展目录),框架核心think,trait目录,extend目录对应的命名空间,文件路径信息已经装载到Loader::$prefixLengthsPsr4, Loader::$prefixDirsPsr4,Loader:: $fallbackDirsPsr4,Loader::$classMap这几个属性中。后面自动加载函数Loader::autoload($class),就是通过这几个属性找到对应的类文件,加载进来。

 2.2自动加载函数Loader::autoload();

先通过self::$classAlias属性确定类和目录的映射,php的系统函数class_alias可以把类加载进来,并且可以使用别名来new这个类。正常情况我们通过Loader::findFile()找到类文件路径,然后include进来。

2.2.1Loader::findFile()过程,通过类找到对应的类文件路径

这个过程,就是通过Loader::$prefixLengthsPsr4, Loader::$prefixDirsPsr4,Loader:: $fallbackDirsPsr4,Loader::$classMap这几个属性中确定类文件路径。理解了这几个属性的格式,也就理解系统如何加载类文件了。

Loader::$classMap这个属性值是通过文件缓存获取类文件路径的,在根目录使用命令 php think optimize:autoload,会在runtime目录生成classmap.php文件。

Loader::$prefixLengthsPsr4的打印结果:

array(2) {//命名空间第一个字母为key  ["t"]=  array(3) {    //命名空间为key, 命名空间字符长度为value    ["thinkcomposer"]= int(15)    ["think"]= int(6)    ["traits"]=int(7)  }  ["a"]=  array(1) {    ["app"]=int(4)  }}

 Loader::$prefixDirsPsr4的打印结果:

array(4) {//命名空间key,绑定的目录为value  ["thinkcomposer"]=  array(1) {    [0]=string(69) "C:xampphtdocstp5.1vendorcomposer/../topthink/think-installer/src"  }  ["app"]=  array(1) {    [0]=string(55) "C:xampphtdocstp5.1vendorcomposer/../../application"  }  ["think"]=  array(1) {    [0]=string(44) "C:xampphtdocstp5.1thinkphplibrarythink"  }  ["traits"]=  array(1) {    [0]= string(45) "C:xampphtdocstp5.1thinkphplibrarytraits"  }}

 Loader:: $fallbackDirsPsr4打印结果

array(1) {  [0]=string(28) "C:xampphtdocstp5.1extend"}

findFile过程中,确定类文件路径是通过目录+类.php拼接而成的。比如实例化thinkError,拼接到的文件路径为"C:xampphtdocstp5.1thinkphplibrarythinkError.php"。伪代码如下:

//$class就是thinkError$logicalPathPsr4 = strtr($class, '\', DIRECTORY_SEPARATOR) . '.php';//通过属性$prefixDirsPsr4查找到文件$file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length);//通过属性$fallbackDirsPsr4查找到文件$file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4//通过属性$classmap查找文件$file = $classmap[$class];

2.3添加命名空间

// 注册应用命名空间Loader::addNamespace($this-namespace, $this-appPath);主动添加命名空间和对应的目录地址。

其实是把相关信息写入Loader::$prefixLengthsPsr4, Loader::$prefixDirsPsr4这两个属性。 

比如application目录的命名空间为app, 在框架启动的应用初始化时initialize(),会注册app命名空间和目录,这样使用application目录的类的时候,自动加载函数才能找到类文件。

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

产品经理

手机 : 13312967497

擅长 : 小程序流量变现

扫码领取礼包

热门模板

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎