在写 PHP 程序时,传统的加载库的方式是 require/require_once 一个库文件。但随着时代的发展,一个复杂的 PHP 项目要加载的库文件越来越多,这个时候会发现使用传统的 require 方式是一件很麻烦的事情(你是否记得每个文件开头 require_once 一大堆文件的年代?)。PHP 小组也意识到这个问题,所以从 PHP5 开始推出 __autoload 函数。利用此函数,可以实现库文件的自动加载:
function __autoload($className)
{
require "/path/to/{$className}.class.php";
}
只要在 bootstrap 文件中加上以上代码,当一个 class 或者 interface 被调用的时候,都会以 class 或者 interface 的名字为参数调用此函数,并按照 __autoload 定义的方式去加载所需要的库文件。
这种方式在一定程度上解决了自动加载的问题,但是随之而来又有了新的问题:如果多个库文件自动加载的方式不一样,比如路径或者规则不同,那么在一个 __autoload 函数体里想要描述所有的库文件自动加载的方式是非常的麻烦的,需要大量的判断(如果 ClassName 是 Foo 开头的就按照 Foo 库的规则载入,如果是 Bar 开头的就按照 Bar 库的规则载入……)。所以从 PHP5.1 开始,又出现了新的自动加载方式,利用 spl_autoload_register 来注册某个库自己的加载方式:
// FooLoader.class.php
class FooLoader
{
static public function registerAutoload()
{
spl_autoload_register(__CLASS__.'::loadClass');
}
static public function loadClass($className)
{
require dirname(__FILE__)."/{$className}.class.php";
}
}
这样只用 require 一下此 FooLoader.class.php 文件,然后在 bootstrap 里面调用FooLoader::registerAutoload() 方法,整个 Foo 库里的所有 class 都能实现自动加载,如果有另外一个 Bar 库,他也有自己的加载方式,那么 bootstrap 也只用再 require 一下 Bar 库里的自动加载文件,然后也调用将其自动加载方法注册到 php autoloader 里的方法就行。
这种方式在 PHP5.1 以及 PHP5.2 的年代很流行,几乎成为了一种行业标准,像一些大的框架比如 zendframework 或者 symfony,以及一些流行的 PHP 工具库比如 swiftmail,都提供了自己的 autoloader。
不知道大家发现没有,这种方式依然有问题。从用户的角度来说,如果他要使用很多第三方库文件,他仍然要为需要自动加载的库文件在 bootstrap 里写出一长串“加载自动加载类文件”以及“调用注册自动加载的方法”的列表,比如我要用 zendframework 以及 symfony 再加上 swiftmailer 这三个库,那么 bootstrap 文件开头处看起来就类似这个样子:
require '/path/to/zf/Autoloader.class.php';
require '/path/to/sf/Autoloader.class.php';
require '/path/to/swift/Autoloader.class.php';
Zend_Autoloader::registerAutoload();
sfAutoloader::registerAutoload();
Swift_Autoloader::registerAutoload();
另外从库文件开发者的角度来说,他们都得为自己的库写一个 autoloader 类。虽然看上去都差不多,但是必须得写。这是不是也算是重复发明轮子的做法呢?所以,PHP 开源社区的同志们为了解决这个问题,打算统一自动加载的规则,这个规则就是 PSR。
在 PSR 里,为 PHP 标准库文件制订了统一的类名/接口名以及对应的库文件路径规则,如果所有的库文件编写者都遵守此规则,那么无论你需要自动加载多少个库文件,在 bootstrap 里面都只用加载一个自动加载类就行了,可能还需要做的,只是把对应的库的名称和库存放的根目录注册在这个自动加载类里面,他会按照PSR制定的标准,准确加载到你所需要的库文件。
如果这个标准推广开来,只要你有一个 autoloader 类,你就可以实现自动加载所有按照这个标准来创建的库文件了。目前就我所知,zendframework 是支持的,PSR 文档的作者就是负责 zf 的 team leader,Symfony2 也是按照这个标准走的,PSR 文档最后提供的自动加载类的作者也就是 sf2 的 team leader。而 swiftmailer 那些目前属于 Symfony2 组件的库,也都是支持的。
另外 PHP 组件管理器 Composer,也更加巧妙的实现了自动加载。它根据下载下来的组件位置,来自动生成自动加载类,让你不用关心库路径在什么地方,也能方便加载所有它管理的库。当然他所能管理的库文件,也都是按照 PSR 的方式来创建的。
总而言之,如果你也想开发自己的开源库,为了你的用户,也为了你自己,更为了整个 PHP 开源社区的成长,不得不开始关心 PSR 标准。
写作累,服务器还越来越贵
求分担,祝愿好人一生平安
天使打赏人