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 相关文章推荐
我的论坛源代码(一)
Oct 09 PHP
PHP中去除换行解决办法小结(PHP_EOL)
Nov 27 PHP
基于PHP编程注意事项的小结
Apr 27 PHP
基于php上传图片重命名的6种解决方法的详细介绍
Apr 28 PHP
解析php如何将日志写进syslog
Jun 28 PHP
PHP循环函数使用介绍之PHP基础入门教程
Sep 21 PHP
php使用memcoder将视频转成mp4格式的方法
Mar 12 PHP
PHP代码判断设备是手机还是平板电脑(两种方法)
Oct 19 PHP
php上传图片并压缩的实现方法
Dec 22 PHP
php json中文编码为null的解决办法
Dec 14 PHP
yii2.0整合阿里云oss上传单个文件的示例
Sep 19 PHP
PHP设计模式(一)工厂模式Factory实例详解【创建型】
May 02 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
WINDOWS服务器安装多套PHP的另类解决方案
2006/10/09 PHP
CodeIgniter框架过滤HTML危险代码
2014/06/12 PHP
PHP模板引擎Smarty内建函数foreach,foreachelse用法分析
2016/04/11 PHP
Laravel如何使用Redis共享Session
2018/02/23 PHP
Alliance vs Liquid BO3 第一场2.13
2021/03/10 DOTA
JS中字符问题(二进制/十进制/十六进制及ASCII码之间的转换)
2008/11/03 Javascript
javascript 设计模式之单体模式 面向对象学习基础
2010/04/18 Javascript
Colortip基于jquery的信息提示框插件在IE6下面的显示问题修正方法
2010/12/06 Javascript
jquery实现的省市区三级联动
2015/04/02 Javascript
jQuery Html控件基本操作(日常收集整理)
2016/03/11 Javascript
Bootstrap每天必学之折叠(Collapse)插件
2016/04/25 Javascript
js获取form表单所有数据的简单方法
2016/08/18 Javascript
jQuery插入节点和移动节点用法示例(insertAfter、insertBefore方法)
2016/09/08 Javascript
原生js实现简单的Ripple按钮实例代码
2017/03/24 Javascript
JavaScript30 一个月纯 JS 挑战中文指南(英文全集)
2017/07/23 Javascript
jquery 遍历hash操作示例【基于ajax交互】
2019/10/12 jQuery
vue实现将数据存入vuex中以及从vuex中取出数据
2019/11/08 Javascript
javascript 代码是如何被压缩的示例代码
2020/05/06 Javascript
对vuex中store和$store的区别说明
2020/07/24 Javascript
vue 计算属性和侦听器的使用小结
2021/01/25 Vue.js
python发送arp欺骗攻击代码分析
2014/01/16 Python
python嵌套函数使用外部函数变量的方法(Python2和Python3)
2016/01/31 Python
Python变量和数据类型详解
2017/02/15 Python
python数据批量写入ScrolledText的优化方法
2018/10/11 Python
python pillow模块使用方法详解
2019/08/30 Python
关于numpy数组轴的使用详解
2019/12/05 Python
requests在python中发送请求的实例讲解
2021/02/17 Python
HTML5 背景的显示区域实现
2020/07/09 HTML / CSS
俄罗斯马克西多姆家居用品网上商店:Максидом
2020/02/06 全球购物
巴西24小时在线药房:Droga Raia
2020/05/12 全球购物
高一新生军训方案
2014/05/12 职场文书
乡镇领导班子四风对照检查材料
2014/09/27 职场文书
2014年社区妇联工作总结
2014/12/02 职场文书
2016年学校安全教育月活动总结
2016/04/06 职场文书
史上最全书信经典范文大全(建议收藏)
2019/07/10 职场文书
Golang 结构体数据集合
2022/04/22 Golang