PHP自动加载
PHP自动加载
框架固然是干活的好工具,但是你知道你平时new 一个新类的时候,发生了什么吗?有想过为什么我们遵循规范就会自动的帮我们做好一切的加载吗? 让我们一切来探索发现其中的奥秘。
时间线
蒸汽时代
在PHP 代码的顶部你是不是经常看到这样的代码。
require 'lionis.php';require 'is.php';require 'cool.php';
如果只是引入几个PHP 脚本,那还可以接受。那引入成千上万个脚本的时候,爆炸是在所难免的。如果对一个脚本改了个名字,还需要对引入改脚本的每个脚本改名,能不爆炸吗?连打出这段话都怎么绕。
电气时代
在PHP 电气时代,开始出现了__autoload 和spl_autoload_register 函数注册自定义的自动加载策略。
通俗的来说,__autoload 和spl_autoload_register 是一个杀手组织,他们会去雇佣各国杀手函数。当我们想搞定某个人的时候new,只需要提供名字类名,剩下的杀手会帮我们搞定的。
__autoload
PHP 5 开始提供这个函数传送门。当你使用的类找不到的时候,它把类名当成参数扔进这个函数。
$lionis = new Lionis;
输出
欧耶耶, 我就是Lionis
spl_autoload_register
如果我们项目很大很老又或者你是一个爱折腾的少先队员,需要引入的东西有不一样的规范,这时候如果都放在autoload 函数里,这个函数马上就会膨胀的。而且autoload 是全局唯一的,如果被人占用了,可能会导致错误。欲使一个人灭亡,必将先使其膨胀。
PHP 5.1.2 开始提供这个函数传送门,注册给定的函数作为
__autoload 的实现。所以,我们看一些框架或插件在自己使用的时候,为了兼容可能会出现function_existsspl_autoload_register。
// 函数spl_autoload_register'lionisIsCoolFind';// 匿名函数
spl_autoload_registerfunction$require require './' . $classname . '.php';
;// 类中的函数spl_autoload_registerarray'Lionis', 'loadClass';
欧耶,这下我们可以写很多不同的自动加载函数了。
信息时代
师傅小心,前面有妖气! 。如果我们每个人都自己实现一套自动加载的方法,每个PHP 组件和框架都使用独特的自动加载器,而且每个框架使用不同的逻辑加载PHP类、接口和性状。
那当我们使用一些第三方框架的时候,还需要去弄清楚引导文件中的自动加载器,那样是有多和时间过不去呢。PHP-FIG 认识到了这个问题了,推荐使用PSR-4 规范,来促进组件之间的互操作性,这样我们
就可以使用一个自动加载器了。
PSR-4 规范
利用命名空间的前缀和文件系统中的目录对应起来。
映射关系为
namespace = filePath\Lionis\Cool = cool
带有命名空间的类
创建一个对象
这个时候,按照PSR-4 的规范,自动加载器应该去加载cool/ 目录下的Real.php。
不对!那这样不是还要自己去实现自动加载器嘛,不然怎么无中生有出现自动加载器呢?难道官方内置了?
你out 了吧,我们可以使用依赖管理器por 来生成PSR-4 自动加载器。你可能会疑问,那我的旧项目没有遵循PSR-4 规范怎么办?嘿嘿,让我们来探索发现一下por 是怎么解决这个问题的吧。
Compor
哦吼吼,我们这次的重点在与探究自动加载,所以por 的安装和使用等,就不去讨论了。
por 自动加载设置了4种加载方式:
PSR-0
PSR-4
classmap
files
PSR-0
要求命名空间和目录层层对应,且可以使用_ 作为路径分隔符,但是这会导致目录结果变得过深。
在por 执行install 等操作时,por 会把文件中的配置存储在vendor/por/autoload_psr0.php文件中的返回数组中。
例如:定义了Very\Good=vendor\Lionis\IsReal\Cool,在调用u Very\Good\Love\SomeClass,PSR-0 加载的实际目录为
vendor/Lionis/IsReal/Cool/Very/Good/Love/SomeClass.php。
对吧,这简直深得吓人,所以PSR-0 被官方废除了。但是一些主流的框架已经实现了PSR-0,为了向下兼容还是要实现PSR-0。
por.json配置:“autoload": "psr-0": "Very\\Good":
"vendor\Lionis\IsReal\Cool"
PSR-4
PSR-4 是现在比较推荐的方法,用于替代PSR-0。
与PSR-0 不同的是,取消掉了_ 作为分隔符和目录结构。
在por 执行install 等操作时,por 会把文件中的配置存储在vendor/por/autoload_psr4.php文件中的返回数组中。
例如:定义了Very\Good=vendor\Lionis\IsReal\Cool,在调用u Very\Good\
Love\SomeClass,PSR-4 加载的.实际目录为
vendor/Lionis/IsReal/Cool/Love/SomeClass.php。
por.json配置:
"autoload": "psr-4": "Very\\Good": "vendor\Lionis\IsReal\Cool"
classmap
classmap 通过配置指定的目录和文件,在por 执行install 等操作时,por 会去扫描对应的目录下以.php结尾的文件中的class,并存储在vendor/por/autoload_classmap.php文件中的返回数组中。
por.json配置:"autoload": "classmap": [ "Lionis/", "Xiaoer/"
]
如果Lionis 下有一个叫VeryCool的文件,那么在
vendor/por/autoload_classmap.php 中会生成。
$baDir . '/Lionis/VeryCool.php', // 其他的映射;
files
files 就是直接简单粗暴的加载文件。在por 执行install 等操作时,por 会把文件中的配置存储在vendor/por/autoload_static.php
文件中的生成一个$files 数组。
por.json 配置:"autoload": "files": ["Lionis/Very/Cool.php"]
小结
por 通过使用por.json,用json 的格式来指定我们需要自动加载的规则。我们只要在入口文件引入vendor/autoload.php 就能很方便的便能使用自动加载。
如果你对por 实现自动加载的原理感兴趣,可以顺着vendor 中的autoload.php 去看看源码。
总结