博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
composer 自动载入 autoload 的使用详解 psr0/psr4/classmap/files
阅读量:6426 次
发布时间:2019-06-23

本文共 4182 字,大约阅读时间需要 13 分钟。

hot3.png

composer 的自动载入 autoload 可以很方便的帮我们快速的构建一套自己的框架结构。

而自动载入本身其实是利用命名空间进行对应规则或标准的路径映射,从而找到我们所需的类文件,读取载入都当前运行时。利用命名空间的自动载入都是懒加载形式的,并不会让程序变得臃肿,但懒加载在一定程度上也影响了程序的性能,要在程序规模和运行效率上做一个折中的选择。

四种模式

psr-0 标准 autoload_namespaces

懒加载,将目标目录作为基目录再进行命名空间和路径的映射后继续向后加载

// php 的 psr-0 规范的自动载入,是将目标目录作为命名空间的基目录再进行路径映射载入类文件"psr-0": {    "Psr0\\Lib\\": "psr0/lib/src/"}

这里还有一点是需要注意的,下划线 _ 对 psr-0 是有特殊意义的。psr-0 的加载器会将类名中的 _ 解析成目录分隔符。

即 Foo_Bar_Test 类会去加载 Foo/Bar/Test.php 文件。

// PSR-0 lookupif (false !== $pos = strrpos($class, '\\')) {    // namespaced class name    $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)        . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);} else {    // PEAR-like class name    $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;}

也可以看下composer 的源码,可以看到是将 _ 替换成了 DIRECTORY_SEPARATOR(目录分隔符)。

在 php 5.2 之前,是没有 namespace 关键字去友好的管理类包的,是 php 5.3 以后才有新特性:命名空间,匿名函数,静态延迟绑定。

然而有很多普遍使用的第三方类库还是使用的下划线的方式去命名类,比如 PHPExcel,这里我们可以看下其官方的 composer.json 文件里自动载入的配置:

"autoload": {    "psr-0": {        "PHPExcel": "Classes/"    }}

则 PHPExcel 顶级类下的检索都会以 Classes 文件夹为起始目录,比如我想使用 PHPExcel_Cell_DataType 这个类。我就可以判断出这个类是在 Classes/PHPExcel/Cell/DataType.php 文件中。

// 则会加载 Classes/PHPExcel/Cell/DataType.phpuse PHPExcel_Cell_DataType;

 

psr-4 标准 autoload_psr4

懒加载,将目标目录直接映射为命名空间对应的目录继续向后加载

// php 的 psr-4 规范的自动载入,是将目标目录直接影射为命名空间的"psr-4": {    "Psr4\\Lib\\": "psr4/lib/src/",    "App\\Controllers\\": "app/controllers/",    "App\\Models\\": "app/models/"}

classmap 模式 autoload_classmap

懒加载,扫描目录下的所有类文件,支持递归扫描, 生成对应的类名=>路径的映射,当载入需要的类时直接取出路径,速度最快

// classmap 扫描目录下的所有类文件 生成对应的类名=>路径的映射"classmap": [    "classmap/lib/src/"]

files 模式

自动载入的文件,主要用来载入一些没办法懒加载的公共函数

// 扫描目录下的所有文件生成 hash => 路径的映射  运行时实时加载// 主要用来载入工具函数"files": [    "ext/common/functions.php",    "ext/system/functions.php"]

框架结构

这里我要尽可能把四种自动载入模式的特征举例出来,所以框架结构并不很合理,不要在意

./├── app│   ├── controllers│   └── models├── classmap│   └── lib│       └── src├── composer.json├── ext│   ├── common│   │   └── functions│   └── system│       └── functions├── psr0│   └── lib│       └── src└── psr4    └── lib        └── src

autoload 规则

编辑 composer.json 文件

{    "autoload": {        "psr-0": {            "Psr0\\Lib\\": "psr0/lib/src/"        },        "psr-4": {            "Psr4\\Lib\\": "psr4/lib/src/",            "App\\Controllers\\": "app/controllers/",            "App\\Models\\": "app/models/"        },        "classmap": [            "classmap/lib/src/"        ],        "files": [            "ext/common/functions.php",            "ext/system/functions.php"        ]    }}

刷新 autoload 规则

composer dump-autoload

当你添加了新的  psr-0/psr-4 的规则,或者在 classmap/files 规则相应的目录下新增了文件时,都需要执行 dump-autoload 来刷新系统的自动载入。

我们可以看一下生成的 psr-0 和 psr-4 标准的自动载入

psr-0:vendor/composer/autoload_namespaces.php

array($baseDir . '/psr0/lib/src'),);

psr-4:vendor/composer/autoload_psr4.php

array($baseDir . '/psr4/lib/src'), 'App\\Models\\' => array($baseDir . '/app/models'), 'App\\Controllers\\' => array($baseDir . '/app/controllers'),);

其实 psr-0/psr-4 的自动载入都将命名空间映射为相应的目录。只不过 psr-0 是映射到目标地址作为基目录再解析命名空间,而 psr-4 是直接映射。

实现一个 psr-0 规范的类文件

psr0/lib/src/Psr0/Lib/Psr0LibClass.php

实现一个 psr-4 规范的类文件

psr4/lib/src/Psr4LibClass.php

classmap 就没什么规范可言了,绝对的一对一映射而已

因为它本身就没遵循命名空间和路径映射的半点规范...随便写一个好了,他的模式其实就是扫描指定目录下的所有文件,把类采集出来,做一个映射表,这个类在这个文件里,完了。

classmap/lib/src/ClassMapAutoload.php

files 是在运行时就直接载入的一些函数文件(非类文件)

ext/common/functions.phpext/system/functions.php

运行一下 compser dump-autoload 来刷新自动载入

实例

运行结果 

#我把全路径隐藏了 就当作在当前工作目录下好了Psr0\Lib\Psr0LibClass@psr0/lib/src/Psr0/Lib/Psr0LibClass.phpPsr4\Lib\Psr4LibClass@psr4/lib/src/Psr4LibClass.phpClassMap\Lib\ClassMapLibClass@classmap/lib/src/ClassMapAutoload.phpApp\Controllers\IndexController@app/controllers/IndexController.phpApp\Models\User@app/models/User.phphello_common@ext/common/functions.phphello_system@ext/system/functions.php

标注:

psr-0 规范同时兼容了 PHP5.2 版本前的为命名空间风格

比如有一个类名为 Foo_Bar_HelloWorld 的类文件存放在

app/Foo/Bar/HelloWorld.php 文件中

"psr-0": {    "Foo\\": "app/"}

便可以将 Foo_Bar_HelloWorld 加载进来,原理其实就是把 _ 替换成路径分隔符 Foo/Bar/HelloWorld 然后进行加载

Foo 命名空间会被基址到 app 目录下,继续按解析好的路径进行加载

new Foo_Bar_HelloWorld();

 

转载于:https://my.oschina.net/sallency/blog/893518

你可能感兴趣的文章
计算机意外地重新启动或遇到错误。windows安装无法继续。若要安装windows 请单击...
查看>>
关于领域驱动设计(DDD)中聚合设计的一些思考
查看>>
水仙花数
查看>>
数据结构——栈
查看>>
changes of mysql 5.6.20
查看>>
阿里巴巴高级技术专家张智宇:阿里聚石塔电商云容器服务应用和实践
查看>>
JavaScript权威设计--JavaScript函数(简要学习笔记十)
查看>>
msyql中查询某个字段的不重复的所有记录
查看>>
VS2010编写WebService与在IIS的发布<之简单讲解>
查看>>
MySQL
查看>>
如何调整WINDOWS进程对多核CPU的利用率?
查看>>
PHP和分布式Memcache的一个小问题 单点故障
查看>>
小灵呼语音系统迁移
查看>>
[MySQL 新特性] MySQL5.6 RC的压缩表自适应padding实现
查看>>
深入线程
查看>>
&lt;&lt;精通iOS开发&gt;&gt;第14章例子代码彻底清除警告
查看>>
jenkins安装
查看>>
ORACLE数据库汉字占几个字节问题
查看>>
UIButton
查看>>
CSS3之边框样式(动画过渡)
查看>>