PHP面试一战到底
上QQ阅读APP看书,第一时间看更新

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如何自动加载类文件?

解答:参考“自动加载”一节的内容。