ZEND内核有一个_zend_executor_globals结构,该结构中的symbol_table就是全局符号表, 其中保存了在顶层作用域中的变量。 函数内部或者对象的方法在被调用时会用active_symbol_table来保存局部变量。 PG(auto_globals_jit) 是一个bool值,默认为true; PHP的全局变量有 _GET,_POST,_COOKIE,_SERVER,_ENV,_REQUEST,_FILES; 其中 _SERVER,_ENV,_REQUEST 比较特别,其他的超级全局变量,默认在 EG(symbol_table)中可以找到。 但是 _SERVER,_ENV,_REQUEST,默认在EG(symbol_table)中找不到,只用用户使用了 $_SERVER, $_ENV,$_REQUEST,才能在EG(symbol_table)中找到。 如果想在 用户不使用 $_SERVER, $_ENV,$_REQUEST 这些变量时,也能在内部获取 $_SERVER, $_ENV,$_REQUEST中的值就要先调用 各自的回调函数。 所以我们在读取_SERVER,_ENV,_REQUEST时必须先判断先是否默认在全局符号表里面了,查看yaf读取全局变量时有如下判断:
#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 4)
zend_bool jit_initialization = (PG(auto_globals_jit) && !PG(register_globals) && !PG(register_long_arrays));
#else
zend_bool jit_initialization = PG(auto_globals_jit);
#endif
先判断auto_globals_jit设置,假如PHP设置没有将_SERVER,_ENV,_REQUEST加到全局符号表中,我们在读取_SERVER,_ENV,_REQUEST时就得主动将其加到symbol_table中,然后才能找到,如:
if (jit_initialization) {
zend_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC);
}
(void)zend_hash_find(&EG(symbol_table), ZEND_STRS("_SERVER"), (void **)&carrier);
zend_is_auto_global方法在Zend/zend_commpile.c文件中,我们可以看到在zend_is_auto_global_quick方法中调用了其回调函数:
zend_bool zend_is_auto_global_quick(const char *name, uint name_len, ulong hashval TSRMLS_DC) /* {{{ */
{
zend_auto_global *auto_global;
ulong hash = hashval ? hashval : zend_hash_func(name, name_len+1);
if (zend_hash_quick_find(CG(auto_globals), name, name_len+1, hash, (void **) &auto_global)==SUCCESS) {
if (auto_global->armed) {
auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
}
return 1;
}
return 0;
}
/* }}} */
zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC) /* {{{ */
{
return zend_is_auto_global_quick(name, name_len, 0 TSRMLS_CC);
}
mark;