1,创建一个扩展
./ext_skel --extname=global
2,扩展global变量
/*定义global变量*/
ZEND_BEGIN_MODULE_GLOBALS(global)
long counter;
char *name;
int name_len;
ZEND_END_MODULE_GLOBALS(global)
ZEND_DECLARE_MODULE_GLOBALS(global);//申明变量
GLOBAL_G(name); //获取global变量的值
GLOBAL_G(counter) = 10; //给global变量赋值
3,POST|GET|COOKIE|SERVER|ENV|REQUEST|FILES全局变量
#php-fpm 生成 POST|GET|COOKIE|SERVER|ENV|REQUEST|FILES全局变量的流程
php_cgi_startup() -> php_module_startup() -> php_startup_auto_globals() -> 保存变量到symbol_table符号表
php_cgi_startup()在 fpm/fpm/fpm_main.c中定义
php_module_startup() 在main/main.c中定义
php_startup_auto_globals() 在main/php_variables.h中定义
zend_hash_update(&EG(symbol_table), "_GET", sizeof("_GET") + 1, &vars, sizeof(zval *), NULL);
/* 读取$_SERVER变量 */
static PHP_FUNCTION(print_server_vars) {
zval **val;
if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **)&val) == SUCCESS) {
RETURN_ZVAL(*val, 1, 0);
}else{
RETURN_FALSE;
}
}
/* 读取$_SERVER[$name] */
ZEND_BEGIN_ARG_INFO(print_server_var_arginfo, 0)
ZEND_ARG_INFO(0, "name")
ZEND_END_ARG_INFO()
static PHP_FUNCTION(print_server_var) {
char *name;
int name_len;
zval **val;
HashTable *ht_vars = NULL;
HashPosition pos;
zval **ret_val;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &name, &name_len) == FAILURE) {
RETURN_NULL();
}
if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **)&val) == SUCCESS) {
ht_vars = Z_ARRVAL_PP(val);
//此处需传入大于name长度+1的值,因为字符串值后面需要'\0'
if (zend_hash_find(ht_vars, name, name_len+1, (void **)&ret_val) == SUCCESS) { RETURN_STRING(Z_STRVAL_PP(ret_val), 0);
}else{
RETURN_NULL();
}
}else{
RETURN_NULL();
}
}
4,$GLOBALS变量
/*添加globals变量*/
static PHP_FUNCTION(add_globals_vars) {
SET_VAR_LONG("_LONG", 10); //添加long变量
SET_VAR_DOUBLE("_DOUBLE", 20.5); //添加double变量
SET_VAR_STRING("_STRING", "string"); //添加string变量
zval *arr;
MAKE_STD_ZVAL(arr);
array_init(arr);
add_assoc_string(arr, "e", "hello", 1);
ZEND_SET_GLOBAL_VAR("_ARRS", arr); //添加zval变量
}
/*添加globals字符串变量*/
5,相关宏
/* 设置global变量 */
#define ZEND_SET_GLOBAL_VAR(name, var) ZEND_SET_SYMBOL(&EG(symbol_table), name, var)
#define ZEND_SET_GLOBAL_VAR_WITH_LENGTH(name, name_length, var, _refcount, _is_ref)
ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), name, name_length, var, _refcount, _is_ref)
/ *设置string类型的global变量 */
#define SET_VAR_STRING(n, v) { { zval *var;
ALLOC_ZVAL(var);
ZVAL_STRING(var, v, 0);
ZEND_SET_GLOBAL_VAR(n, var);}
}
#define SET_VAR_STRINGL(n, v, l) { {zval *var;
ALLOC_ZVAL(var);
ZVAL_STRINGL(var, v, l, 0);
ZEND_SET_GLOBAL_VAR(n, var);}
}
/* 设置long类型的global变量 */
#define SET_VAR_LONG(n, v) {{zval *var;
ALLOC_ZVAL(var);
ZVAL_LONG(var, v);
ZEND_SET_GLOBAL_VAR(n, var);}
}
/* 设置double类型的global变量 */
#define SET_VAR_DOUBLE(n, v) {{ zval *var;
ALLOC_ZVAL(var);
ZVAL_DOUBLE(var, v);
ZEND_SET_GLOBAL_VAR(n, var);}
}
#define ZEND_SET_SYMBOL(symtable, name, var){
char *_name = (name);
ZEND_SET_SYMBOL_WITH_LENGTH(symtable, _name, strlen(_name)+1, var, 1, 0);
}
#define ZEND_SET_SYMBOL_WITH_LENGTH(symtable, name, name_length, var, _refcount, _is_ref){
zval **orig_var;
if (zend_hash_find(symtable, (name), (name_length), (void **) &orig_var)==SUCCESS
&& PZVAL_IS_REF(*orig_var)) {
Z_SET_REFCOUNT_P(var, Z_REFCOUNT_PP(orig_var));
Z_SET_ISREF_P(var);
if (_refcount) {
Z_SET_REFCOUNT_P(var, Z_REFCOUNT_P(var) + _refcount - 1);
}
zval_dtor(*orig_var);
**orig_var = *(var);
FREE_ZVAL(var);
} else {
Z_SET_ISREF_TO_P(var, _is_ref);
if (_refcount) {
Z_SET_REFCOUNT_P(var, _refcount);
}
zend_hash_update(symtable, (name), (name_length), &(var), sizeof(zval *), NULL);
}
}