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 相关文章推荐
MySQL数据源表结构图示
Jun 05 PHP
php横向重复区域显示二法
Sep 25 PHP
PHP 变量定义和变量替换的方法
Jul 30 PHP
centos 5.6 升级php到5.3的方法
May 14 PHP
PHP中extract()函数的定义和用法
Aug 17 PHP
获取PHP警告错误信息的解决方法
Jun 03 PHP
利用php递归实现无限分类 格式化数组的详解
Jun 08 PHP
PHP中几个可以提高运行效率的代码写法、技巧分享
Aug 21 PHP
PHP实现懒加载的方法
Mar 07 PHP
PHP+jQuery实现滚屏无刷新动态加载数据功能详解
May 04 PHP
php制作圆形用户头像的实例_自定义封装类源代码
Sep 18 PHP
php5.x禁用eval的操作方法
Oct 19 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
一拳超人中怪人协会钦定! S级别最强四人!
2020/03/02 日漫
重置版游戏视频
2020/04/09 魔兽争霸
PHP4实际应用经验篇(1)
2006/10/09 PHP
PHPMYADMIN导入数据最大为2M的解决方法
2012/04/23 PHP
php一次性删除前台checkbox多选内容的方法
2013/09/22 PHP
2014年10个最佳的PHP图像操作库
2014/07/14 PHP
php从数组中随机选择若干不重复元素的方法
2015/03/14 PHP
php通过排列组合实现1到9数字相加都等于20的方法
2015/08/03 PHP
PHP基于socket实现的简单客户端和服务端通讯功能示例
2017/07/10 PHP
PHP使用XMLWriter读写xml文件操作详解
2018/07/31 PHP
基于jquery的获取浏览器窗口大小的代码
2011/03/28 Javascript
在Ubuntu上安装最新版本的Node.js
2014/07/14 Javascript
深入理解Javascript中this的作用域
2014/08/12 Javascript
jquery复选框多选赋值给文本框的方法
2015/01/27 Javascript
jquery判断checkbox是否选中及改变checkbox状态的实现方法
2016/05/26 Javascript
JS在Chrome浏览器中showModalDialog函数返回值为undefined的解决方法
2016/08/03 Javascript
jQuery中ScrollTo用法示例
2016/09/04 Javascript
浅谈js继承的实现及公有、私有、静态方法的书写
2016/10/28 Javascript
简单理解Vue条件渲染
2016/12/03 Javascript
js实现点击按钮复制文本功能
2020/07/20 Javascript
AJAX在JQuery中的应用详解
2019/01/30 jQuery
[03:40]DOTA2抗疫特别篇《英雄年代》
2020/02/28 DOTA
学习python处理python编码问题
2011/03/13 Python
python在Windows8下获取本机ip地址的方法
2015/03/14 Python
Django与遗留的数据库整合的方法指南
2015/07/24 Python
Python实现单词翻译功能
2017/06/06 Python
Python实现发送QQ邮件的封装
2017/07/14 Python
python实现批量图片格式转换
2020/06/16 Python
解决pycharm运行出错,代码正确结果不显示的问题
2018/11/30 Python
python 读取Linux服务器上的文件方法
2018/12/27 Python
pytorch-RNN进行回归曲线预测方式
2020/01/14 Python
Python3操作读写CSV文件使用包过程解析
2020/04/10 Python
详解canvas在圆弧周围绘制文本的两种写法
2018/05/22 HTML / CSS
Oracle中delete,truncate和drop的区别
2016/05/05 面试题
歌颂祖国的演讲稿
2014/05/04 职场文书
Python自然语言处理之切分算法详解
2021/04/25 Python