PHP从手动导入到自动加载

前言

在PHP开发过程中,如果希望从外部引入一个 class,通常会使用 include 和 require 方法,去把定义这个 class 的文件包含进来。这个在小规模开发的时候,没什么大问题。但在大型的开发项目中,使用这种方式会带来一些隐含的问题:如果一个 PHP 文件需要使用很多其它类,那么就需要很多的require/include 语句,这样有可能会造成遗漏或者包含进不必要的类文件。如果大量的文件都需要使用其它的类,那么要保证每个文件都包含正确的类文件肯定是一个噩梦, 况且 require_once 的代价很大。

PHP5 为这个问题提供了一个解决方案,这就是类的自动装载 (autoload) 机制。autoload 机制可以使得 PHP 程序有可能在使用类时才自动包含类文件,而不是一开始就将所有的类文件 include 进来,这种机制也称为 lazy loading(懒加载)

总结起来,自动加载功能带来了几处优点:

  • 使用类之前无需 include 或者 require
  • 使用类的时候才会 require/include 文件,实现了 lazy loading(懒加载),避免了 require/include 多余文件
  • 无需考虑引入类的实际磁盘地址,实现了逻辑和实体文件的分离

PHP自动加载函数__autoload()

通常 PHP5 在使用一个类时,如果发现这个类没有加载,就会自动运行 __autoload() 函数,这个函数是我们在程序中自定义的,在这个函数中我们可以加载需要使用的类。下面是个简单的示例:

function __autoload($classname) {
    require_once ($classname . ".php"); 
}

在我们这个简单的例子中,我们直接将类名加上扩展名 ”.php” 构成了类文件名,然后使用 require_once 将其加载。从这个例子中,我们可以看出 autoload 至少要做三件事情:

  1. 根据类名确定类文件名;
  2. 确定类文件所在的磁盘路径(在我们的例子是最简单的情况,类与调用它们的PHP程序文件在同一个文件夹下);
  3. 将类从磁盘文件中加载到系统中。

第三步最简单,只需要使用 include/require 即可。要实现第一步,第二步的功能,必须在开发时约定类名与磁盘文件的映射方法,只有这样我们才能根据类名找到它对应的磁盘文件。

当有大量的类文件要包含的时候,我们只要确定相应的规则,然后在 __autoload() 函数中,将类名与实际的磁盘文件对应起来,就可以实现 lazy loading 的效果。从这里我们也可以看出 __autoload() 函数的实现中最重要的是类名与实际的磁盘文件映射规则的实现。


__autoload() 函数存在的问题

如果在一个系统的实现中,如果需要使用很多其它的类库,这些类库可能是由不同的开发人员编写的,其类名与实际的磁盘文件的映射规则不尽相同。这时如果要实现类库文件的自动加载,就必须在 __autoload() 函数中将所有的映射规则全部实现,这样的话 __autoload() 函数有可能会非常复杂,甚至无法实现。最后可能会导致 __autoload() 函数十分臃肿,这时即便能够实现,也会给将来的维护和系统效率带来很大的负面影响。

那么问题出现在哪里呢?问题出现在 __autoload() 是全局函数只能定义一次,不够灵活,所以所有的类名与文件名对应的逻辑规则都要在一个函数里面实现,造成这个函数的臃肿。那么如何来解决这个问题呢?答案就是使用一个 __autoload 调用堆栈,不同的映射关系写到不同的 __autoload 函数中去,然后统一注册统一管理,这个就是 PHP5 引入的 SPL Autoload。


SPL Autoload

SPL是 Standard PHP Library (标准PHP库)的缩写。它是 PHP5 引入的一个扩展库,其主要功能包括 autoload 机制的实现及包括各种 Iterator 接口或类。SPL Autoload 具体有几个函数:

  • spl_autoload_register:注册__autoload()函数
  • spl_autoload_unregister:注销已注册的函数
  • spl_autoload_functions:返回所有已注册的函数
  • spl_autoload_call:尝试所有已注册的函数来加载类
  • spl_autoload :__autoload() 的默认实现
  • spl_autoload_extionsions: 注册并返回 spl_autoload 函数使用的默认文件扩展名

简单来说,spl_autoload 就是 SPL 自己的定义 __autoload() 函数,功能很简单,就是去注册的目录(由 set_include_path 设置)找与 $classname 同名的 .php/.inc 文件。当然,你也可以指定特定类型的文件,方法是注册扩展名 (spl_autoload_extionsions)。

而 spl_autoload_register() 就是我们上面所说的 autoload 调用堆栈,我们可以向这个函数注册多个我们自己的 __autoload() 函数,当 PHP 找不到类名时,PHP 就会调用这个堆栈,一个一个去调用自定义的 __autoload() 函数,实现自动加载功能。如果我们不向这个函数输入任何参数,那么就会注册 spl_autoload() 函数。


总结

PHP 自动加载的底层就是这些,注册机制已经非常灵活,但是还缺什么呢?我们上面说过,自动加载关键就是类名和文件的映射,这种映射关系不同框架有不同方法,非常灵活,但是过于灵活就会显得杂乱,PHP 有专门对这种映射关系的规范,那就是 PSR 标准中 PSR0 与 PSR4。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值