background image

summary:PHP autoload 机制分析

php

实现

autoload 有两种方法:

1、拦截器__autoload()
2、设置全局变量函数指针 autoload_func 为指定函数。通常在 c 扩展中使用
本质上前者还是通过后者实现的。
分析过程,

PHP5.3.6

源码

=>Zend/zend_vm_def.h  1894 行
ZEND_VM_HANDLER(109,ZEND_FETCH_CLASS,...
=>zend_execute_API.c 1526 行
zend_class_entry *zend_fetch_class(const char *class_name,...
=>zend_execute_API.c 1564 行
if(zend_lookup_class_ex(class_name,class_name_len,...
=>zend_execute_API.c 1039 行
ZEND_API int zend_lookup_class_ex(const char *na...
=>zend_execute_API.c 1121 行
retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC);
=>zend_execute_API.c 758 行
       zend_call_function
顾名思义,

zend_call_function 的主要功能是调用 PHP 函数。其参数 fcall_info, fcall_cache,

分别指向两个重要的结构,

zend_fcall_info 和 zend_fcall_info_cache

zend_call_function 主要工作流程如下:
如果

fcall_cache.function_handler 不为 NULL,则直接执行 fcall_cache.function_handler 指向

的函数。
如果

 fcall_cache.function_handler 为 NULL,则尝试查找函数名为 fcall_info.function_name 的

 数,如果存在的话,则执行之;

 
则总结为如下,
autoload 机制的主要执行过程为:
(1) 检查执行器全局变量函数指针 autoload_func 是否为 NULL。
(2) 如果 autoload_func 不为 NULL,则直接执行 autoload_func 指针指向的函数用来加载类,
并不检查

__autoload()函数是否定义。

(3) 如果 autoload_func 为 NULL,则查找系统中是否定义有__autoload()函数。如果没有定义,
则报告错误并退出;如果定义了

__autoload()函数,则执行__autoload()尝试加载类,并返回

加载结果。
自动加载方便了面向对象和代码复用,但是多个类库不同的

__autoload 又会导致混乱。

可以用

spl_autoload 解决,将不同开发者的拦截器函数都注册到自动加载函数的 hashtable

中。
spl 实现自动加载的机制是维护一个 hashtable,里面存储有具有自动加载功能的各个函数。
当触发自动加载机制时,

zend 会在遍历执行这个 hashtable 里面的函数,直到成功加载类或

加载失败后返回。
当 需 要 使 用 自 动 加 载 功 能 时 , 使 用 函 数

spl_autoload_register() 或

spl_autoload_register('autoloadfuncitonname')
无参的

spl_autoload_register()会默认加载 spl_autoload()函数,该函数功能有限,只能在

inlcude_path 中搜索指定扩展名的类库。