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&mysql(三)
Oct 09 PHP
smtp邮件发送一例
Oct 09 PHP
PHP中call_user_func_array()函数的用法演示
Feb 05 PHP
深入PHP许愿墙模块功能分析
Jun 25 PHP
php中利用str_pad函数生成数字递增形式的产品编号
Sep 30 PHP
ThinkPHP连接数据库及主从数据库的设置教程
Aug 22 PHP
PHP使用CURL实现多线程抓取网页
Apr 30 PHP
谈谈你对Zend SAPIs(Zend SAPI Internals)的理解
Nov 10 PHP
PHP 数组基本操作方法详解
Jun 17 PHP
PHP+MariaDB数据库操作基本技巧备忘总结
May 21 PHP
Windows平台PHP+IECapt实现网页批量截图并创建缩略图功能详解
Aug 02 PHP
基于thinkphp6.0的success、error实现方法
Nov 05 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
《OVERLORD》手游英文版即将上线 手机上也能扮演骨王
2020/04/09 日漫
php使用sql数据库 获取字段问题介绍
2013/08/12 PHP
PHP连接MySQL的2种方法小结以及防止乱码
2014/03/11 PHP
Linux下PHP加速器APC的安装与配置笔记
2014/10/24 PHP
Yii2中cookie用法示例分析
2016/07/18 PHP
Nginx实现反向代理
2017/09/20 Servers
php服务器的系统详解
2019/10/12 PHP
prototype1.4中文手册
2006/09/22 Javascript
js parseInt("08")未指定进位制问题
2010/06/19 Javascript
jquery 删除字符串最后一个字符的方法解析
2014/02/11 Javascript
JS执行删除前的判断代码
2014/02/18 Javascript
JS动态改变表格边框宽度的方法
2015/03/31 Javascript
javaScript中Math()函数注意事项
2015/06/18 Javascript
jquery实现美观的导航菜单鼠标提示特效代码
2015/09/06 Javascript
实例剖析AngularJS框架中数据的双向绑定运用
2016/03/04 Javascript
微信小程序 教程之wxapp视图容器 swiper
2016/10/19 Javascript
整理一下常见的IE错误
2016/11/18 Javascript
jQuery UI 实例讲解 - 日期选择器(Datepicker)
2017/09/18 jQuery
jquery实现侧边栏左右伸缩效果的示例
2017/12/19 jQuery
vue axios基于常见业务场景的二次封装的实现
2018/09/21 Javascript
Koa 使用小技巧(小结)
2018/10/22 Javascript
three.js如何实现3D动态文字效果
2021/03/03 Javascript
Python中使用动态变量名的方法
2014/05/06 Python
Python导出DBF文件到Excel的方法
2015/07/25 Python
用ReactJS和Python的Flask框架编写留言板的代码示例
2015/12/19 Python
Python计算两个日期相差天数的方法示例
2017/05/23 Python
python读取大文件越来越慢的原因与解决
2019/08/08 Python
python numpy存取文件的方式
2020/04/01 Python
CSS3属性box-sizing使用指南
2014/12/09 HTML / CSS
工商技校毕业生自荐信
2013/11/15 职场文书
学习十八大宣传标语
2014/10/09 职场文书
竞聘书的秘诀
2019/04/02 职场文书
sass 常用备忘案例详解
2021/09/15 HTML / CSS
Python字符串常规操作小结
2022/04/03 Python
Linux中文件的基本属性介绍
2022/06/01 Servers
Go语言编译原理之源码调试
2022/08/05 Golang