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开发GUI
Oct 09 PHP
推荐文章系统(一)
Oct 09 PHP
PHP下对数组进行排序的函数
Aug 08 PHP
thinkphp在模型中自动完成session赋值示例代码
Sep 09 PHP
php将数组转换成csv格式文件输出的方法
Mar 14 PHP
PHP实现微信发红包程序
Aug 24 PHP
php连接oracle数据库的方法(测试成功)
May 26 PHP
Yii2表单事件之Ajax提交实现方法
May 04 PHP
Ajax中的JSON格式与php传输过程全面解析
Nov 14 PHP
从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解
Apr 03 PHP
laravel 实现向公共模板中传值 (view composer)
Oct 22 PHP
PHP RabbitMQ消息列队
May 11 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单例模式实现方法分析
2015/03/14 PHP
php实现模拟登陆方正教务系统抓取课表
2015/05/19 PHP
PHP Try-catch 语句使用技巧
2016/02/28 PHP
php版微信公众号自定义分享内容实现方法
2016/09/22 PHP
prototype与jquery下Ajax实现的差别
2009/09/13 Javascript
在IE6下发生Internet Explorer cannot open the Internet site错误
2010/06/21 Javascript
从JQuery源码分析JavaScript函数的apply方法与call方法
2014/09/25 Javascript
JavaScript从0开始构思表情插件
2016/07/26 Javascript
JS图片预加载插件详解
2017/06/21 Javascript
Vue Spa切换页面时更改标题的实例代码
2017/07/15 Javascript
echarts学习笔记之图表自适应问题详解
2017/11/22 Javascript
JS实现非首屏图片延迟加载的示例
2018/01/06 Javascript
JavaScript基于对象方法实现数组去重及排序操作示例
2018/07/10 Javascript
如何让node运行es6模块文件及其原理详解
2018/12/11 Javascript
[01:56]林书豪DOTA2上海特级锦标赛励志短片
2016/03/05 DOTA
Python学习笔记之常用函数及说明
2014/05/23 Python
Python实现简易端口扫描器代码实例
2017/03/15 Python
教你学会使用Python正则表达式
2017/09/07 Python
Python编写一个优美的下载器
2018/04/15 Python
Python从ZabbixAPI获取信息及实现Zabbix-API 监控的方法
2018/09/17 Python
Python龙贝格法求积分实例
2020/02/29 Python
python正则表达式的懒惰匹配和贪婪匹配说明
2020/07/13 Python
CSS3中background-clip和background-origin的区别示例介绍
2014/03/10 HTML / CSS
Html5无刷新修改browser Url的方法
2014/01/15 HTML / CSS
澳大利亚领先的在线礼品网站:Gifts Australia
2020/08/15 全球购物
EJB timer的种类
2014/10/28 面试题
大学生应聘自荐信
2013/10/11 职场文书
校长就职演讲稿
2014/01/06 职场文书
幼师求职自荐信范文
2014/01/26 职场文书
开工仪式主持词
2014/03/20 职场文书
教育专业毕业生推荐信
2014/07/10 职场文书
安全生产工作汇报材料
2014/10/28 职场文书
师范生见习报告
2014/10/31 职场文书
考试没考好检讨书(精选篇)
2014/11/16 职场文书
试用期旷工辞退通知书
2015/04/17 职场文书
德能勤绩工作总结
2015/08/11 职场文书