5.2 自动加载
在一个文件里使用一个类,我们可以用include、require来引入类文件。
例如,Cat类定义在cat.php文件里,请看示例代码:(源码文件:ch05/autoload/require/cat.php)
在test.php里使用Cat类,可以使用include、require函数引入cat.php文件。程序实现如下:(源码文件:ch05/autoload/require/test.php)
<?php require './cat.php'; //require_once './cat.php'; //include './cat.php'; //include_once './cat.php'; $tom = new Cat(); $tom->eat(); //Output cat eat fish
但如果需要引入多个文件,使用引入函数就非常低效了:
require './cat.php'; require './dog.php'; require './monkey.php'; require './elephant.php';
为了解决自动加载的问题,PHP提供了三种解决方案:__autoload、spl_autoload和spl_autoload。
5.2.1 __autoload
__autoload是魔术方法,当调用未定义的类时,_autoload()会被调用,用于按照规则加载未定义的类。
__autoload定义如下:
void __autoload ( string $class )
参数是要调用的类名。实现__autoload方法的一般步骤如下:
步骤01 由类名找到对应的文件名。
步骤02 判断文件是否存在。
步骤03 用include、require等函数引入文件。
为了说明__autoload的使用方法,我们编写了一个示例,请查看autoload/autoload目录。
示例中的文件结构如下:
cat.php dog.php monkey.php test.php
我们在调用时,不使用引入函数,直接实现__autoload方法。上面的目录结构比较简单,文件名是类名的小写形式,路径在当前目录下查找。
程序实现代码如下:(源码文件:ch05/autoload/autoload/test.php)
需要注意的是,__autoload在PHP 7.2.0中已被废弃。
__autoload不能重复定义,只能注册一个,这在协作项目或需要引入多个第三方包时,变得非常不方便。所以PHP引入spl_autoload_register来解决这个问题。
5.2.2 spl_autoload_register
为了解决多个自动加载函数的问题,PHP引入了spl_autoload_register函数。其定义如下:
为了说明__autoload的使用方法,我们编写了一个示例,请查看autoload/spl_autoload_register目录。
示例中的文件结构如下:
由于表示动物的类分成大型动物(big_animal)和小型动物(small_animal),所以需要两个加载函数:
spl_autoload_register允许多个加载函数,是非常有用的一个功能。如果从composer安装一个第三方包,那个包可以自行处理自动加载,而作为使用者无须关心。这使得协作和开源变得更加便利。
关于__autoload与spl_autoload_register的比较如表5-2所示。
表5-2 __autoload与spl_autoload_register的比较
5.2.3 spl_autoload
spl_autoload是__autoload的一个默认实现,当spl_autoload_register无参数时默认调用。其实现的功能为在include路径里查找类。
以下是一个使用示例:
可以看到,spl_autoload只能设置路径和文件后缀,所以在实际项目中应用较少,属于鸡肋功能。
5.2.4 面试题:引用文件函数的区别
题目描述1:include、require、inclue_once、require_once有什么区别?
解答:include和require的区别是当引入文件过程中遇到错误,include会提示错误并继续执行,而require会终止运行。
inclue_once和require_once则保证脚本执行期间的文件引用不超过1次,避免函数重定义,变量重新赋值等问题。
题目描述2:PHP如何自动加载类文件?
解答:参考“自动加载”一节的内容。