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 相关文章推荐
C# Assembly类访问程序集信息
Jun 13 PHP
php 生成饼图 三维饼图
Sep 28 PHP
php 中文字符入库或显示乱码问题的解决方法
Apr 12 PHP
PHP与Java进行通信的实现方法
Oct 21 PHP
三种php连接access数据库方法
Nov 11 PHP
php switch语句多个值匹配同一代码块的实现
Mar 03 PHP
PHP的反射类ReflectionClass、ReflectionMethod使用实例
Aug 05 PHP
PHP封装的字符串加密解密函数
Dec 18 PHP
CodeIgniter配置之autoload.php自动加载用法分析
Jan 20 PHP
在Yii2特定页面如何禁用调试工具栏Debug Toolbar详解
Aug 07 PHP
PHP实现通过strace定位故障原因的方法
Apr 29 PHP
Laravel Eloquent ORM 多条件查询的例子
Oct 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
example2.php
2006/10/09 PHP
在Windows中安装Apache2和PHP4的权威指南
2006/10/09 PHP
php基础知识:控制结构
2006/12/13 PHP
php 动态添加记录
2009/03/10 PHP
laravel 5异常错误:FatalErrorException in Handler.php line 38的解决
2017/10/12 PHP
PHP+Ajax实现上传文件进度条动态显示进度功能
2018/06/04 PHP
jquery1.4后 jqDrag 拖动 不可用
2010/02/06 Javascript
javascript改变position值实现菜单滚动至顶部后固定
2013/01/18 Javascript
Js冒泡事件详解及阻止示例
2014/03/21 Javascript
JQuery实现带排序功能的权限选择实例
2015/05/18 Javascript
jquery mobile界面数据刷新的实现方法
2016/05/28 Javascript
jQuery插件uploadify实现ajax效果的图片上传
2016/06/18 Javascript
js querySelector() 使用方法
2016/12/21 Javascript
bootstrap select插件封装成Vue2.0组件
2017/04/17 Javascript
基于JavaScript实现前端数据多条件筛选功能
2020/08/19 Javascript
JavaScript定义及输出螺旋矩阵的方法详解
2017/12/01 Javascript
浅谈Vue2.0中v-for迭代语法的变化(key、index)
2018/03/06 Javascript
详解Nuxt.js部署及踩过的坑
2018/08/07 Javascript
vue中使用gojs/jointjs的示例代码
2018/08/24 Javascript
一百行JS代码实现一个校验工具
2019/04/30 Javascript
关于引入vue.js 文件的知识点总结
2020/01/28 Javascript
详解JavaScript原型与原型链
2020/11/16 Javascript
python3.5 tkinter实现页面跳转
2018/01/30 Python
对numpy中array和asarray的区别详解
2018/04/17 Python
Python中dict和set的用法讲解
2019/03/28 Python
使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件及出现问题解决方法
2019/09/06 Python
Python 转移文件至云对象存储的方法
2021/02/07 Python
法国太阳镜店:Sunglasses Shop
2016/08/27 全球购物
size?爱尔兰官方网站:英国伦敦的球鞋精品店
2019/03/31 全球购物
外贸采购员岗位职责
2014/03/08 职场文书
美术兴趣小组活动总结
2014/07/07 职场文书
应届毕业生自荐信
2015/03/04 职场文书
雷锋之歌观后感
2015/06/10 职场文书
西安事变观后感
2015/06/12 职场文书
卫生主题班会
2015/08/14 职场文书