PHP之autoload运行机制实例分析


Posted in PHP onAugust 28, 2014

本文较为深入的分析了PHP的autoload运行机制。对于深入理解PHP运行原理有一定的帮助作用。具体分析如下:

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中搜索指定扩展名的类库。

有参的spl_autoload_register()默认不再加载spl_autoload()函数。
可以通过spl_autoload_functions()查看当前自动加载hashtable中的函数,该函数返回一个数组

注意:使用spl_autoload时,系统会忽略拦截器__autoload,除非显式地使用spl_autoload_register('__autoload')将其加入hashtable

希望本文所述对大家的PHP程序设计有所帮助

PHP 相关文章推荐
树型结构列出指定目录里所有文件的PHP类
Oct 09 PHP
Drupal 添加模块出现莫名其妙的错误的解决方法(往往出现在模块较多时)
Apr 18 PHP
php session劫持和防范的方法
Nov 12 PHP
php定界符
Jun 19 PHP
PHP实现图片压缩的两则实例
Jul 19 PHP
php5.3提示Function ereg() is deprecated Error问题解决方法
Nov 12 PHP
php简单解析mysqli查询结果的方法(2种方法)
Jun 29 PHP
PHP页面跳转实现延时跳转的方法
Dec 10 PHP
利用Laravel生成Gravatar头像地址的优雅方法
Dec 30 PHP
PHP实现打包zip并下载功能
Jun 12 PHP
PHP7生产环境队列Beanstalkd用法详解
May 19 PHP
PHP中的异常处理机制深入讲解
Nov 10 PHP
php+MySQL判断update语句是否执行成功的方法
Aug 28 #PHP
PHP反射机制用法实例
Aug 28 #PHP
PHP对象相互引用的内存溢出实例分析
Aug 28 #PHP
PHP对象递归引用造成内存泄漏分析
Aug 28 #PHP
PHP中cookie和session的区别实例分析
Aug 28 #PHP
PHP实现视频文件上传完整实例
Aug 28 #PHP
PHP获取表单所有复选框的值的方法
Aug 28 #PHP
You might like
星际流派综述
2020/03/04 星际争霸
图象函数中的中文显示
2006/10/09 PHP
推荐个功能齐全的发送PHP邮件类
2007/01/03 PHP
PHP中常用的转义函数
2014/02/28 PHP
搭建Vim为自定义的PHP开发工具的一些技巧
2015/12/11 PHP
详解PHP使用Redis存储session时的一个Warning定位
2017/07/05 PHP
PHP排序算法之基数排序(Radix Sort)实例详解
2018/04/21 PHP
Yii框架小部件(Widgets)用法实例详解
2020/05/15 PHP
获取网站跟路径的javascript代码(站点及虚拟目录)
2009/10/20 Javascript
nodejs win7下安装方法
2012/05/24 NodeJs
JS自动缩小超出大小的图片
2012/10/12 Javascript
Jquery each方法跳出循环,并获取返回值(实例讲解)
2013/12/12 Javascript
html+js实现简单的计算器代码(加减乘除)
2016/07/12 Javascript
Ajax跨域实现代码(后台jsp)
2017/01/21 Javascript
jquery DataTable实现前后台动态分页
2017/06/17 jQuery
vue项目开发中setTimeout等定时器的管理问题
2018/09/13 Javascript
微信小程序基础教程之worker线程的使用方法
2019/07/15 Javascript
微信小程序实现蓝牙打印
2019/09/23 Javascript
使用 Vue-TCB 快速在 Vue 应用中接入云开发的方法
2020/02/10 Javascript
Python3实现生成随机密码的方法
2014/08/23 Python
python实现计算资源图标crc值的方法
2014/10/05 Python
Python创建系统目录的方法
2015/03/11 Python
Python实现对比不同字体中的同一字符的显示效果
2015/04/23 Python
Windows下Eclipse+PyDev配置Python+PyQt4开发环境
2016/05/17 Python
Django应用程序中如何发送电子邮件详解
2017/02/04 Python
pandas获取groupby分组里最大值所在的行方法
2018/04/20 Python
Python爬虫信息输入及页面的切换方法
2018/05/11 Python
对python 数据处理中的LabelEncoder 和 OneHotEncoder详解
2018/07/11 Python
详解从Django Allauth中进行登录改造小结
2019/12/18 Python
python argparse模块通过后台传递参数实例
2020/04/20 Python
Django用户认证系统如何实现自定义
2020/11/12 Python
StubHub西班牙:购买和出售全球活动门票
2017/06/05 全球购物
美国最大的家庭鞋类零售商之一:Shoe Carnival
2017/10/06 全球购物
国际贸易专业推荐信
2013/11/15 职场文书
仓库门卫岗位职责
2013/12/22 职场文书
高校教师个人工作总结2014
2014/12/17 职场文书