PHP的自动加载机制

今天讲一下PHP的自动加载机制:

从PHP5开始,PHP支持两种自动加载的方式,一种是__autoload,另一种是spl_autoload。

第一种在PHP脚本中实现__autoload就可以了,它会在试图使用尚未定义的类时自动调用,通过调用此函数,脚本引擎在PHP出错失败前有了最后一个机会加载所需的类。

第二种方式,spl_autoload_register提供了一种更加灵活的方式来实现类的自动加载。其目的是也是为了取代__autoload函数。

那么两种自动加载到底是在什么时候被触发的呢?下面我们根据Zend原来做详细的解析:

先来看看什么时候出发自动加载的,在Zend/zend_execute_API.c中

<pre name="code" class="cpp">ZEND_API int zend_lookup_class_ex(const char *name, int name_length, ......);

 

如果类不存在,就会调用两种自动加载:

<pre name="code" class="cpp"> fcall_info.size = sizeof(fcall_info);
    fcall_info.param_count = 1;
    fcall_info.no_separation = 1;
 
    fcall_cache.initialized = EG(autoload_func) ? 1 : 0;
    fcall_cache.function_handler = EG(autoload_func);
    fcall_cache.calling_scope = NULL;
    fcall_cache.called_scope = NULL;
    fcall_cache.object_ptr = NULL;
 
    zend_exception_save(TSRMLS_C);
    retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC);
 

这里有一个很重要的函数zend_call_function,她有两个重要的指针形参数fcall_info, fcall_cache,它们分别指向两个重要的结构,一个是zend_fcall_info, 另一个是zend_fcall_info_cache。zend_call_function主要工作流程如下:如果fcall_cache.function_handler指针为NULL,则尝试查找函数名为fcall_info.function_name的函数,如果存在的话,则执行之;如果fcall_cache.function_handler不为NULL,则直接>执行fcall_cache.function_handler指向的函数。

PHP在实例化一个对象时(实际上在实现接口,使用类常数或类中的静态变量,调用类中的静态方法时都会如此),首先会在系统中查找该类(或接口)是否存在,如果不存在的话就尝试使用autoload机制来加载该类。而autoload机制的主要执行过程为:

(1) 检查执行器全局变量函数指针autoload_func是否为NULL。
(2) 如果autoload_func==NULL, 则查找系统中是否定义有__autoload()函数,如果没有,则报告错误并退出。
(3) 如果定义了__autoload()函数,则执行__autoload()尝试加载类,并返回加载结果。
(4) 如果autoload_func不为NULL,则直接执行autoload_func指针指向的函数用来加载类。注意此时并不检查__autoload()函数是否定义。

真相终于大白,PHP提供了两种方法来实现自动装载机制,一种我们前面已经提到过,是使用用户定义的__autoload()函数,这通常在PHP源程>序中来实现;另外一种就是设计一个函数,将autoload_func指针指向它,这通常使用C语言在PHP扩展中实现。如果既实现了__autoload()函数,又实现了autoload_func(将autoload_func指向某一PHP函数),那么只执行autoload_func函数。

最后在啰嗦两句,现在流行的C扩展PHP框架是如何实现自动加载的?其实并没有神秘之处,她也是调用了spl_autoload_register,把在扩展中实现的自动加载函数注册到自动加载函数队列中去。

根据类名及类名与文件地址映射关系找到真实的类文件,并编译执行,最后把类名放入hash class_table便完成自动加载。


我的原创博客Yence地址: http://www.yence.cn/item/detail/8.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值