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世纪万年历
Dec 06 PHP
一个典型的PHP分页实例代码分享
Jul 28 PHP
PHP编程入门的基本语法知识点总结
Jan 26 PHP
关于PHP中Session文件过多的问题及session文件保存位置
Mar 17 PHP
基于PHP制作验证码
Oct 12 PHP
PHP上传图片时判断上传文件是否为可用图片的方法
Oct 20 PHP
php mysql实现mysql_select_db选择数据库
Dec 30 PHP
php 截取GBK文档某个位置开始的n个字符方法
Mar 08 PHP
PHP基于堆栈实现的高级计算器功能示例
Sep 15 PHP
php swoole多进程/多线程用法示例【基于php7nts版】
Aug 12 PHP
php写入txt乱码的解决方法
Sep 17 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
mantis安装、配置和使用中的问题小结
2014/07/14 PHP
PHP中使用xmlreader读取xml数据示例
2014/12/29 PHP
使用WAMP搭建PHP本地开发环境
2017/05/10 PHP
PHP实现基于回溯法求解迷宫问题的方法详解
2017/08/17 PHP
PHP中使用CURL发送get/post请求上传图片批处理功能
2018/10/15 PHP
php面向对象基础详解【星际争霸游戏案例】
2020/01/23 PHP
JS在IE和FireFox之间常用函数的区别小结
2010/03/12 Javascript
jQuery 美元符冲突的解决方法
2010/03/28 Javascript
JavaScript prototype属性深入介绍
2012/11/27 Javascript
Javascript闭包(Closure)详解
2015/05/05 Javascript
js事件监听器用法实例详解
2015/06/01 Javascript
jQuery事件绑定on()、bind()与delegate() 方法详解
2015/06/03 Javascript
学习Bootstrap组件之下拉菜单
2015/07/28 Javascript
javascript实现的猜数小游戏完整实例代码
2016/05/10 Javascript
简单实现jQuery级联菜单
2017/01/09 Javascript
Angular.Js之Scope作用域的学习教程
2017/04/27 Javascript
vue+iview+less+echarts实战项目总结
2018/02/22 Javascript
JavaScript中arguments和this对象用法分析
2018/08/08 Javascript
Vue中android4.4不兼容问题的解决方法
2018/09/04 Javascript
javascript实现5秒倒计时并跳转功能
2019/06/20 Javascript
vue实现图片懒加载的方法分析
2020/02/05 Javascript
Python实现识别手写数字 Python图片读入与处理
2020/03/23 Python
pandas DataFrame数据转为list的方法
2018/04/11 Python
python实现图片识别汽车功能
2018/11/30 Python
Python Tkinter 简单登录界面的实现
2019/06/14 Python
Python生成验证码、计算具体日期是一年中的第几天实例代码详解
2019/10/16 Python
python单例模式原理与创建方法实例分析
2019/10/26 Python
python使用scapy模块实现ARP扫描的过程
2021/01/21 Python
html5-canvas中使用clip抠出一个区域的示例代码
2018/05/25 HTML / CSS
详解HTML5中CSS外观属性
2020/09/10 HTML / CSS
罗兰·穆雷官网:Roland Mouret
2018/09/28 全球购物
面向对象编程是如何提高软件开发水平的
2014/05/06 面试题
专业见习报告范文
2014/11/03 职场文书
班主任经验交流材料
2014/12/16 职场文书
Django数据库(SQlite)基本入门使用教程
2022/07/07 Python
Win11如何查看显卡型号 Win11查看显卡型号的方法
2022/08/14 数码科技