background image

CODE:

/* autoload.php */
<?php
function __autoload($classname) {
  require_once ($classname . "class.php");
}

$person = new Person("Altair", 6);
var_dump ($person);
?>通常 PHP5 在使用一个类时,如果发现这个类没有加载,就会自动运行__autoload()函数,
在这个函数中我们可以加载需要使用的类。在我们这个简单的例子中,我们直接将类名加上
扩展名

".class.php"构成了类文件名,然后使用 require_once 将其加载。从这个例子中,我们

可以看出

autoload 至少要做三件事情,第一件事是根据类名确定类文件名,第二件事是确

定类文件所在的磁盘路径

(在我们的例子是最简单的情况,类与调用它们的 PHP 程序文件

在同一个文件夹下

),第三件事是将类从磁盘文件中加载到系统中。第三步最简单,只需要

使用

include/require 即可。要实现第一步,第二步的功能,必须在开发时约定类名与磁盘文

件的映射方法,只有这样我们才能根据类名找到它对应的磁盘文件。

因此,当有大量的类文件要包含的时候,我们只要确定相应的规则,然后在

__autoload()函

数中,将类名与实际的磁盘文件对应起来,就可以实现

lazy loading 的效果。从这里我们也

可以看出

__autoload()函数的实现中最重要的是类名与实际的磁盘文件映射规则的实现。

但现在问题来了,如果在一个系统的实现中,如果需要使用很多其它的类库,这些类库可
能是由不同的开发人员编写的,其类名与实际的磁盘文件的映射规则不尽相同。这时如果要
实现类库文件的自动加载,就必须在

__autoload()函数中将所有的映射规则全部实现,这样

的话

__autoload()函数有可能会非常复杂,甚至无法实现。最后可能会导致__autoload()函数

十分臃肿,这时即便能够实现,也会给将来的维护和系统效率带来很大的负面影响。在这种
情况下,难道就没有更简单清晰的解决办法了吧?答案当然是:

NO! 在看进一步的解决方

法之前,我们先来看一下

PHP 中的 autoload 机制是如何实现的。

(2) PHP 的 autoload 机制的实现

我们知道,

PHP 文件的执行分为两个独立的过程,第一步是将 PHP 文件编译成普通称之为

OPCODE 的字节码序列(实际上是编译成一个叫做 zend_op_array 的字节数组),第二步是
由一个虚拟机来执行这些

OPCODE。PHP 的所有行为都是由这些 OPCODE 来实现的。因此,

为了研究

PHP 中 autoload 的实现机制,我们将 autoload.php 文件编译成 opcode,然后根据

这些

OPCODE 来研究 PHP 在这过程中都做了些什么:

CODE:

/* autoload.php 编译后的 OPCODE 列表,是使用作者开发的 OPDUMP 工具
     * 生成的结果,可以到网站 http://www.phpinternals.com/ 下载该软件。
      */
    1: <?php
    2:  // require_once ("Person.php");