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 相关文章推荐
教你IIS6的PHP最佳配置方法
Sep 05 PHP
分页显示Oracle数据库记录的类之一
Oct 09 PHP
php中理解print EOT分界符和echo EOT的用法区别小结
Feb 21 PHP
php笔记之:文章中图片处理的使用
Apr 26 PHP
用mysql_fetch_array()获取当前行数据的方法详解
Jun 05 PHP
解析php中curl_multi的应用
Jul 17 PHP
PHP连接数据库实现注册页面的增删改查操作
Mar 27 PHP
PHP预定义变量9大超全局数组用法详解
Apr 23 PHP
PHP数组实例详解
Jun 26 PHP
yii的入口文件index.php中为什么会有这两句
Aug 04 PHP
Zend Framework处理Json数据方法详解
Dec 09 PHP
PHP设计模式之观察者模式定义与用法示例
Aug 04 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怎样调用MSSQL的存储过程
2006/10/09 PHP
如何在PHP中使用Oracle数据库(4)
2006/10/09 PHP
php中生成随机密码的自定义函数代码
2013/10/21 PHP
php构造函数的继承方法
2015/02/09 PHP
Laravel5.1 框架响应基本用法实例分析
2020/01/04 PHP
jQuery 渐变下拉菜单
2009/12/15 Javascript
hover的用法及live的用法介绍(鼠标悬停效果)
2013/03/29 Javascript
jquery交替变换颜色的三种方法 实例代码
2013/11/19 Javascript
JavaScript DOM进阶方法
2015/04/13 Javascript
JavaScript中利用各种循环进行遍历的方式总结
2015/11/10 Javascript
无缝滚动的简单实现代码(推荐)
2016/06/07 Javascript
Highcharts学习之数据列
2016/08/03 Javascript
jstree单选功能的实现方法
2017/06/07 Javascript
vue.js组件之间传递数据的方法
2017/07/10 Javascript
深入理解ES6学习笔记之块级作用域绑定
2017/08/19 Javascript
JS秒杀倒计时功能完整实例【使用jQuery3.1.1】
2019/09/03 jQuery
原生js canvas实现鼠标跟随效果
2020/08/02 Javascript
[52:36]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
python抓取网页时字符集转换问题处理方案分享
2014/06/19 Python
python线程、进程和协程详解
2016/07/19 Python
Python 字典与字符串的互转实例
2017/01/13 Python
Tensorflow的梯度异步更新示例
2020/01/23 Python
Python实现分数序列求和
2020/02/25 Python
Python GUI编程学习笔记之tkinter事件绑定操作详解
2020/03/30 Python
Python使用tkinter制作在线翻译软件
2021/02/22 Python
英国航空官网:British Airways
2016/09/11 全球购物
班级寄语大全
2014/04/10 职场文书
小学五年级学生评语
2014/04/22 职场文书
幼儿园课题实施方案
2014/05/14 职场文书
设备售后服务承诺书
2014/05/30 职场文书
乡党委干部党的群众路线教育实践活动个人对照检查材料思想汇报
2014/10/01 职场文书
入股协议书范本
2014/11/01 职场文书
上课说话检讨书
2015/01/27 职场文书
项目合作意向书
2015/05/08 职场文书
贴吧吧主申请感言
2015/08/03 职场文书
Navicat Premium自定义 sql 标签的创建方式
2022/09/23 数据库