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生成WAP页面
Oct 09 PHP
php 数组的合并、拆分、区别取值函数集
Feb 15 PHP
PHP 验证码的实现代码
Jul 17 PHP
PHP在不同页面间传递Json数据示例代码
Jun 08 PHP
CodeIgniter框架数据库事务处理的设计缺陷和解决方案
Jul 25 PHP
Yii视图CGridView列表用法实例分析
Jul 12 PHP
Yii2实现多域名跨域同步登录退出
Feb 04 PHP
PHP大文件分割上传 PHP分片上传
Aug 28 PHP
PHP实现的AES加密、解密封装类与用法示例
Aug 02 PHP
PHP中一个有趣的preg_replace函数详解
Aug 15 PHP
Laravel5.3+框架定义API路径取消CSRF保护方法详解
Apr 06 PHP
浅谈php常用的7大框架的优缺点
Jul 20 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
php使用curl和正则表达式抓取网页数据示例
2014/04/13 PHP
php使用$_POST或$_SESSION[]向js函数传参
2014/09/16 PHP
PHP return语句另类用法不止是在函数中
2014/09/17 PHP
php实现微信企业转账功能
2018/10/02 PHP
Yii 框架使用Forms操作详解
2020/05/18 PHP
基于jQuery的淡入淡出可自动切换的幻灯插件
2010/08/24 Javascript
jquery isType() 类型判断代码
2011/02/14 Javascript
javascript设计模式之中介者模式Mediator
2014/12/30 Javascript
jquery+easeing实现仿flash的载入动画
2015/03/10 Javascript
JavaScript实现打字效果的方法
2015/07/10 Javascript
js实现文字在按钮上滚动的方法
2015/08/20 Javascript
JavaScript获取当前运行脚本文件所在目录的方法
2016/02/03 Javascript
使用JQuery实现智能表单验证功能
2016/03/08 Javascript
jQuery插件datatables使用教程
2016/04/21 Javascript
jquery组件WebUploader文件上传用法详解
2020/10/23 Javascript
vue动态生成dom并且自动绑定事件
2017/04/19 Javascript
Vue-router结合transition实现app前进后退动画切换效果的实例
2017/10/11 Javascript
简述JS控制台的使用
2018/07/15 Javascript
解决Vue在封装了Axios后手动刷新页面拦截器无效的问题
2018/11/08 Javascript
jQuery设置下拉框显示与隐藏效果的方法分析
2019/09/15 jQuery
vue各种事件监听实例(小结)
2020/06/24 Javascript
Python单例模式的两种实现方法
2017/08/14 Python
python散点图实例之随机漫步
2018/08/27 Python
python中的print()输出
2019/04/12 Python
Python3 Tkinter选择路径功能的实现方法
2019/06/14 Python
解决springboot yml配置 logging.level 报错问题
2020/02/21 Python
哈工大自然语言处理工具箱之ltp在windows10下的安装使用教程
2020/05/07 Python
购买美国制造的相框和画框架:Picture Frames
2018/08/14 全球购物
几个SQL的面试题
2014/03/08 面试题
Linux管理员面试题 Linux admin interview questions
2016/07/08 面试题
综合测评自我鉴定
2013/10/08 职场文书
营销与策划专业求职信
2014/06/20 职场文书
超搞笑婚前保证书
2015/05/08 职场文书
2015年迎新晚会策划书
2015/07/16 职场文书
合作意向书范本
2019/04/17 职场文书
Python 的 sum() Pythonic 的求和方法详细
2021/10/16 Python