html5中文学习网

您的位置: 首页 > 网络编程 > PHP编程 » 正文

PHP源码分析之Global关键字_PHP教程_编程技术

[ ] 已经帮助:人解决问题

 pNZHTML5中文学习网 - HTML5先行者学习网

  闲来无事,就系统的从PHP的词法分析,语法分析,opcodes生成,执行,整个流程,详细的分析了global关键字的实现。pNZHTML5中文学习网 - HTML5先行者学习网

  当你在脚本中写下:pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  <?phppNZHTML5中文学习网 - HTML5先行者学习网

  $var = "laruence";pNZHTML5中文学习网 - HTML5先行者学习网

  function sample(){pNZHTML5中文学习网 - HTML5先行者学习网

  global $var;pNZHTML5中文学习网 - HTML5先行者学习网

  }pNZHTML5中文学习网 - HTML5先行者学习网

  ?>pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  的时候,你知道PHP是怎么实现在函数作用域找到全局变量的么?pNZHTML5中文学习网 - HTML5先行者学习网

  在我前面的文章中(深入理解PHP原理之Opcodes)讲过, PHP的执行,经历了如下几个阶段:pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  1. Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)pNZHTML5中文学习网 - HTML5先行者学习网

  2. Parsing, 将Tokens转换成简单而有意义的表达式pNZHTML5中文学习网 - HTML5先行者学习网

  3. Compilation, 将表达式编译成OpocdespNZHTML5中文学习网 - HTML5先行者学习网

  4. Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  那么,第一阶段,自然就是Scanning了, 在词法分析阶段,我们的pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  global $var;pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  会被解析为:pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  T_GLOBAL var;pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  接下来是parsing阶段:pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  T_GLOBAL var;pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  yacc经过规则:pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  statement:pNZHTML5中文学习网 - HTML5先行者学习网

   T_GLOBAL global_var_list ';'pNZHTML5中文学习网 - HTML5先行者学习网

  ....pNZHTML5中文学习网 - HTML5先行者学习网

  global_var_list:pNZHTML5中文学习网 - HTML5先行者学习网

  global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }pNZHTML5中文学习网 - HTML5先行者学习网

   global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }pNZHTML5中文学习网 - HTML5先行者学习网

  ;pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  其中, zend_do_fetch_global_variable是真正生成opcode的函数:pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  zend_op *opline;pNZHTML5中文学习网 - HTML5先行者学习网

  ......pNZHTML5中文学习网 - HTML5先行者学习网

  opline->opcode = ZEND_FETCH_W;pNZHTML5中文学习网 - HTML5先行者学习网

  opline->result.op_type = IS_VAR;pNZHTML5中文学习网 - HTML5先行者学习网

  ......pNZHTML5中文学习网 - HTML5先行者学习网

  opline->op2.u.EA.type = ZEND_FETCH_GLOBAL_LOCK;pNZHTML5中文学习网 - HTML5先行者学习网

 pNZHTML5中文学习网 - HTML5先行者学习网

  而对于ZEND_FETCH_W的op_handler是:pNZHTML5中文学习网 - HTML5先行者学习网

  ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONSTTMPVARCV, ANY) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W); }pNZHTML5中文学习网 - HTML5先行者学习网

  我们来看看zend_fetch_var_adress_helper:pNZHTML5中文学习网 - HTML5先行者学习网

  ..... 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() } }pNZHTML5中文学习网 - HTML5先行者学习网

  可以看出,核心就是zend_get_targer_symbol_table这个函数了:pNZHTML5中文学习网 - HTML5先行者学习网

  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;}pNZHTML5中文学习网 - HTML5先行者学习网

  恩,问题清楚了,也就是说, 如果你global了一个变量,那么Zend就会去全局symbol_table去寻找,如果找不到,就会在全局symbol_table中分配相应的变量。pNZHTML5中文学习网 - HTML5先行者学习网

  通过这样的机制,实现了全局变量。pNZHTML5中文学习网 - HTML5先行者学习网

pNZHTML5中文学习网 - HTML5先行者学习网
pNZHTML5中文学习网 - HTML5先行者学习网
(责任编辑:)
推荐书籍
推荐资讯
关于HTML5先行者 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助