资源描述:
《深入理解PHP原理之foreach》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、foreach是PHP中很常用的一个用作数组循环的控制语句。因为它的方便和易用,自然也就在后端隐藏着很复杂的具体实现方式(对用户透明)今天,我们就来一起分析分析,foreach是如何实现数组(对象)的遍历的。本节内容涉及到较多编译原理(lexandyacc)的知识,所以如果您觉得看不太懂,可以先找相关的资料看看。我们知道PHP是一个脚本语言,也就是说,用户编写的PHP代码最终都是会被PHP解释器解释执行,特别的,对于PHP来说,所有的用户编写的PHP代码,都会被翻译成PHP的虚拟机ZE的虚拟指令(OPCODES)来执行(参看:深入理解
2、PHP原理之Opcodes).不论细节的话,就是说,我们所编写的任何PHP脚本,都会最终被翻译成一条条的指令,从而根据指令,由相应的C编写的函数来执行。那么foreach会被翻译成什么样子呢?1.foreach($arras$key=>$val){2. echo$key.'=>'.$val."";3.}在词法分析阶段,foreach会被识别为一个TOKEN:T_FOREACH,在语法分析阶段,会被规则:1. unticked_statement://没有被绑定ticks的语句2. //有省略3
3、.
4、T_FOREACH'('variableT_AS4. {zend_do_foreach_begin(&$1,&$2,&$3,&$4,1TSRMLS_CC);}5. foreach_variableforeach_optional_arg')'{zend_do_foreach_cont(&$1,&$2,&$4,&$6,&$7TSRMLS_CC);}6. foreach_statement{zend_do_foreach_end(&$1,&$4TSRMLS_CC);}7.
5、T_
6、FOREACH'('expr_without_variableT_AS8. {zend_do_foreach_begin(&$1,&$2,&$3,&$4,0TSRMLS_CC);}9. variableforeach_optional_arg')'{zend_check_writable_variable(&$6);zend_do_foreach_cont(&$1,&$2,&$4,&$6,&$7TSRMLS_CC);}10. foreach_statement{zend_do_foreach_
7、end(&$1,&$4TSRMLS_CC);}11. //有省略12.;仔细分析这段语法规则,我们可以发现,对于:foreach($arras$key=>$val){echo$key.‘=>’.$val.””;}会被分析为:1. T_FOREACH'('variableT_AS{zend_do_foreach_begin('foreach','(',$arr,'as',1TSRMLS_CC);}2. foreach_variableforeach_optional_arg(T_DOUBLE
8、_ARROWforeach_variable)')'{zend_do_foreach_cont('foreach','(','as',$key,$valTSRMLS_CC);}3. foreach_satement{zend_do_foreach_end('foreach','as');}然后,让我们来看看foreach_statement:它其实就是一个代码块,体现了我们的echo$key.‘=>’.$val.””;T_ECHOexpr;显然,实现foreach的核心就是如下3个函数:zend_do_f
9、oreach_beginzend_do_foreach_contzend_do_foreach_end其中,zend_do_foreach_begin(代码太长,直接写伪码)主要做了:1.记录当前的opline行数(为以后跳转而记录)2.对数组进行RESET(讲内部指针指向第一个元素)3.获取临时变量($val)4.设置获取变量的OPCODEFE_FETCH,结果存第3步的临时变量4.记录获取变量的OPCODES的行数而对于zend_do_foreach_cont来说:1.根据foreach_variable的u.EA.type来判断
10、是否引用2.根据是否引用来调整zend_do_foreach_begin中生成的FE_FETCH方式3.根据zend_do_foreach_begin中记录的取变量的OPCODES的行数,来初始化循环(主要处理在循环内部