php的类有全局变量吗_php 全局变量

描述

PHP中把定义在函数、类之外的变量称之为全局变量,也就是定义在主脚本中的变量,这些变量可以在函数、成员方法中通过global关键字引入使用。

1 functiontest() {2 global $id;3 $id++;4 }5

6 $id = 1;7 test();8 echo $id;

存储

全局变量在整个请求执行期间始终存在,它们保存在EG(symbol_table)中,也就是全局变量符号表,与静态变量的存储一样,这也是一个哈希表,主脚本(或include、require)在zend_execute_ex执行开始之前会把当前作用域下的所有局部变量添加到EG(symbol_table)中

zend_vm_execute.h中,i_init_execute_data()这个函数中会把局部变量插入到EG(symbol_table):

1 ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value)2 {3 ...4 i_init_execute_data(execute_data, op_array, return_value);5 zend_execute_ex(execute_data);6 ...7 }

i_init_execute_data会把局部变量插入到EG(symbol_table),定义在zend_execute.c

1 static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /*{{{*/

2 {3 ZEND_ASSERT(EX(func) == (zend_function*)op_array);4

5 EX(opline) = op_array->opcodes;6 EX(call) =NULL;7 EX(return_value) =return_value;8

9 zend_attach_symbol_table(execute_data);10

11 if (!op_array->run_time_cache) {12 op_array->run_time_cache = emalloc(op_array->cache_size);13 memset(op_array->run_time_cache, 0, op_array->cache_size);14 }15 EX_LOAD_RUN_TIME_CACHE(op_array);16 EX_LOAD_LITERALS(op_array);17

18 EG(current_execute_data) =execute_data;19 }

zend_attach_symbol_table 把局部变量插入到EG(symbol_table),定义在zend_execute_API.c中

1 ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /*{{{*/

2 {3 zend_op_array *op_array = &execute_data->func->op_array;4 HashTable *ht = execute_data->symbol_table; //全局变量符号表

5

6 /*copy real values from symbol table into CV slots and create7 INDIRECT references to CV in symbol table*/

8 if (EXPECTED(op_array->last_var)) {9 zend_string **str = op_array->vars; //局部变量

10 zend_string **end = str + op_array->last_var;//最后一个局部变量的位置

11 zval *var = EX_VAR_NUM(0);12

13 do{14 zval *zv = zend_hash_find(ht, *str);15

16 if(zv) {17 if (Z_TYPE_P(zv) ==IS_INDIRECT) {18 zval *val =Z_INDIRECT_P(zv);19

20 ZVAL_COPY_VALUE(var, val);21 } else{22 ZVAL_COPY_VALUE(var, zv);23 }24 } else{25 ZVAL_UNDEF(var);26 zv = zend_hash_add_new(ht, *str, var);//添加到全局变量符号表

27 }28 ZVAL_INDIRECT(zv, var);29 str++;//指向下一个局部变量

30 var++;31 } while (str !=end);32 }33 }

注意局部变量通过偏移量来访问,而不是变量名

从上面的过程可以很直观的看到,在执行前遍历局部变量,然后插入EG(symbol_table),EG(symbol_table)中的value直接指向局部变量的zval,示例经过这一步的处理之后(此时局部变量只是分配了zval,但还未初始化,所以是IS_UNDEF):

访问

与静态变量的访问一样,全局变量也是将原来的值转换为引用,然后在global导入的作用域内创建一个局部变量指向该引用:

1 global $id; //相当于:$id = & EG(symbol_table)["id"];

销毁局部变量如果没有手动销毁,那么在函数执行结束时会将它们销毁,而全局变量则是在整个请求结束时才会销毁,即使是我们直接在PHP脚本中定义在函数外的那些变量。

1 void shutdown_destructors(void)2 {3 if(CG(unclean_shutdown)) {4 EG(symbol_table).pDestructor =zend_unclean_zval_ptr_dtor;5 }6 zend_try {7 uint32_t symbols;8 do{9 symbols = zend_hash_num_elements(&EG(symbol_table));10 //销毁

11 zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor);12 } while (symbols != zend_hash_num_elements(&EG(symbol_table)));13 }14 ...15 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值