闲来无事,就系统的从PHP的词法分析,语法分析,opcodes生成,执行,整个流程,详细的分析了global关键字的实现。
当你在脚本中写下:
$var = "laruence";
function sample(){
global $var;
}
?>
的时候,你知道PHP是怎么实现在函数作用域找到全局变量的么?
在我前面的文章中(深入理解PHP原理之Opcodes)讲过, PHP的执行,经历了如下几个阶段:
1. Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)
2. Parsing, 将Tokens转换成简单而有意义的表达式
3. Compilation, 将表达式编译成Opocdes
4. Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。
那么,第一阶段,自然就是Scanning了, 在词法分析阶段,我们的
global $var;
会被解析为:
T_GLOBAL var;
接下来是parsing阶段:
T_GLOBAL var;
yacc经过规则:
statement:
T_GLOBAL global_var_list ';'
....
global_var_list:
global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
;
其中, zend_do_fetch_global_variable是真正生成opcode的函数:
zend_op *opline;
......
opline->opcode = ZEND_FETCH_W;
opline->result.op_type = IS_VAR;
......
opline->op2.u.EA.type = ZEND_FETCH_GLOBAL_LOCK;
而对于ZEND_FETCH_W的op_handler是:
ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONSTTMPVARCV, ANY) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W); }
我们来看看zend_fetch_var_adress_helper:
..... target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC);/* if (!target_symbol_table) { ZEND_VM_NEXT_OPCODE(); }*/ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) { switch (type) { case BP_VAR_R: case BP_VAR_UNSET: zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); /* break missing intentionally */ case BP_VAR_IS: retval = &EG(uninitialized_zval_ptr); break; case BP_VAR_RW: zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); /* break missing intentionally */ case BP_VAR_W: { zval *new_zval = &EG(uninitialized_zval); new_zval->refcount++; zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval); } break; EMPTY_SWITCH_DEFAULT_CASE() } }
可以看出,核心就是zend_get_targer_symbol_table这个函数了:
static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_variable *Ts, int type, zval *variable TSRMLS_DC){ switch (opline->op2.u.EA.type) { case ZEND_FETCH_LOCAL: return EG(active_symbol_table); break; case ZEND_FETCH_GLOBAL: case ZEND_FETCH_GLOBAL_LOCK: return &EG(symbol_table); break; case ZEND_FETCH_STATIC: if (!EG(active_op_array)->static_variables) { ALLOC_HASHTABLE(EG(active_op_array)->static_variables); zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0); } return EG(active_op_array)->static_variables; break; EMPTY_SWITCH_DEFAULT_CASE() } return NULL;}
恩,问题清楚了,也就是说, 如果你global了一个变量,那么Zend就会去全局symbol_table去寻找,如果找不到,就会在全局symbol_table中分配相应的变量。
通过这样的机制,实现了全局变量。

您是否在Windows安装程序页面上看到“出现问题”以及“OOBELANGUAGE”语句?Windows的安装有时会因此类错误而停止。OOBE表示开箱即用的体验。正如错误提示所表示的那样,这是与OOBE语言选择相关的问题。没有什么可担心的,你可以通过OOBE屏幕本身的漂亮注册表编辑来解决这个问题。快速修复–1.单击OOBE应用底部的“重试”按钮。这将继续进行该过程,而不会再打嗝。2.使用电源按钮强制关闭系统。系统重新启动后,OOBE应继续。3.断开系统与互联网的连接。在脱机模式下完成OOBE的所

Windows上的激活过程有时会突然转向显示包含此错误代码0xc004f069的错误消息。虽然激活过程已经联机,但一些运行WindowsServer的旧系统可能会遇到此问题。通过这些初步检查,如果这些检查不能帮助您激活系统,请跳转到主要解决方案以解决问题。解决方法–关闭错误消息和激活窗口。然后,重新启动计算机。再次从头开始重试Windows激活过程。修复1–从终端激活从cmd终端激活WindowsServerEdition系统。阶段–1检查Windows服务器版本您必须检查您使用的是哪种类型的W

最近,在使用Vue应用开发过程中,我遇到了一个常见的问题:“TypeError:Failedtofetch”错误提示。这个问题出现在使用axios进行HTTP请求时,后端服务器没有正确响应请求时发生。这种错误提示通常表明请求无法到达服务器,可能是由于网络原因或服务器未响应造成的。出现这个错误提示后,我们应该怎么办呢?以下是一些解决方法:检查网络连接由于

很多时候,非常大的文件很难在设备之间共享,尤其是智能手机等。因此,这些文件首先被存档/压缩成RAR文件,然后发送到另一个设备进行共享。但问题是RAR文件不容易在iPhone上提取。要提取zip文件,只需轻点一下即可。没有多少人知道在iPhone上提取RAR文件的过程,对于初学者来说,这些步骤可能会令人困惑。可以使用iPhone上称为快捷方式的默认应用程序来完成此操作。我们在这里逐步解释了如何使用快捷方式应用程序在iPhone上提取任何RAR文件。如何在iPhone上提取RAR文件步骤1:首先,您

透明效果增强了Windows11的视觉吸引力,尤其是任务栏、“开始”菜单和登录屏幕。但我们都有不同的偏好。对于那些不喜欢它的人来说,在Windows11中禁用透明度效果不会花费太多时间。禁用后,背景颜色不会影响操作系统组件的配色方案,并且会采用相当不透明的形式。此外,以下是在Windows11中禁用透明度效果的主要好处:Windows11中的透明度效果可能会影响性能并降低旧电脑的速度。功耗增加,电池寿命缩短,但在大多数情况下并不明显。动画感觉更流畅、更无缝。如何在Windows11上关闭透明效果

事件日志是详细说明主要和次要更改甚至错误的报告。如果服务或启动应用在第一次尝试时无法运行,则会生成日志。但是,当日志数量变得很大时,用户可能希望禁用Windows事件日志。单个日志在磁盘上占用的空间很小,但如果每天生成数千个此类报告并将其存储在SSD上,那么您会看到性能下降。继续阅读以了解如何在Windows中关闭事件日志记录!是否可以禁用Windows事件日志?是的,禁用事件日志没有坏处。请记住,这些日志只是有助于解决问题的报告。他们不执行任何操作或自动解决手头的问题。对于许多用户来说,令人惊

Windows安全中心应用中缺少本地安全机构(LSA)选项背后的可能原因可能是Windows安全中心主要组件损坏。有时,如果你有一段时间没有更新系统,Windows安全中心的定义可能会变得非常过时。这些是应该可以帮助您找回缺失部分的解决方案。修复1–手动创建RunAsPPL密钥创建RunAsPPL键和后续值以修复Windows安全中心中的LSA问题。注意–注册表编辑并非易事。有时,这些编辑可能会出错并且可能很危险。因此,请备份注册表文件,以便以后可以使用。步骤1–您只需要在框中输入“注册表”并按

如何在Zend框架中使用ACL(AccessControlList)进行权限控制导言:在一个Web应用程序中,权限控制是至关重要的一项功能。它可以确保用户只能访问其有权访问的页面和功能,并防止未经授权的访问。Zend框架提供了一种方便的方法来实现权限控制,即使用ACL(AccessControlList)组件。本文将介绍如何在Zend框架中使用ACL


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

SublimeText3 Linux新版
SublimeText3 Linux最新版

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

Atom编辑器mac版下载
最流行的的开源编辑器

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),