王朝网络
分享
 
 
 

PHP的GET/POST等大变量生成过程

王朝php·作者佚名  2008-12-18
宽屏版  字体: |||超大  

· 作者:laruence(http://www.laruence.com/)

· 本文地址:http://www.laruence.com/2008/11/07/581.html

· 转载请注明出处

主要探讨了PHP的大变量的生成过程。另外如果你注意到, 当在表单中提交的input的name中如果有点号的时候, 在PHP中会自动把点号处理成下划线。并且你很想知道这是为什么,在什么时候发生的? 呵呵,本文也就这个问题做了回答。

首先明确一个问题,PHP的变量名中是不能包含点号的。 但是为了处理表单中的点号命名,PHP就会自动把点号(.)转换成下划线(_)。

要知道PHP是怎么处理的,首先我们要了解,$_GET, $_POST, $_COOKIE等变量的构造过程。

在每个请求到来以后,apache处理到response阶段的时候, 会将控制权交给PHP模块, PHP模块会在处理请求之前首先间接调用php_request_startup (具体调用序列是send_php -> apache_php_module_main ->php_request_startup, 关于这部门可以参看我前面的文章(PHP Life Cycle) , 在php_request_startup中:

int

php_request_startup(TSRMLS_D)

{

int

retval=SUCCESS;

#if PHP_SIGCHILD

signal(SIGCHLD,sigchld_handler);

#endif

if

(php_start_sapi()==FAILURE)

{

return

FAILURE;

}

php_output_activate(TSRMLS_C);

sapi_activate(TSRMLS_C);

php_hash_environment(TSRMLS_C);

zend_try

{

PG(during_request_startup)=1;

php_output_activate(TSRMLS_C);

if

(PG(expose_php))

{

sapi_add_header(SAPI_PHP_VERSION_HEADER,sizeof(SAPI_PHP_VERSION_HEADER)-1,1);

}

}

zend_catch

{

retval=FAILURE;

}

zend_end_try();

return

retval;

}

注意其中的php_hash_environment(TSRMLS_C)函数调用 , 这个函数就是在请求处理前, 初始化请求相关的变量的函数。

这个函数定义在: main/php_variables.c中 , 有兴趣的可以看看:

int

php_hash_environment(TSRMLS_D)

{

char*p;

unsigned

char

_gpc_flags[5]={0,0,0,0,0};

zend_bool

jit_initialization=(PG(auto_globals_jit)&& !PG(register_globals)&& !PG(register_long_arrays));

struct

auto_global_record

{

char*name;

uint

name_len;

char*long_name;

uint

long_name_len;

zend_bool

jit_initialization;

}

auto_global_records[]={

{

"_POST",sizeof("_POST"),"HTTP_POST_VARS",sizeof("HTTP_POST_VARS"),0

},

{

"_GET",sizeof("_GET"),"HTTP_GET_VARS",sizeof("HTTP_GET_VARS"),0

},

{

"_COOKIE",sizeof("_COOKIE"),"HTTP_COOKIE_VARS",sizeof("HTTP_COOKIE_VARS"),0

},

{

"_SERVER",sizeof("_SERVER"),"HTTP_SERVER_VARS",sizeof("HTTP_SERVER_VARS"),1

},

{

"_ENV",sizeof("_ENV"),"HTTP_ENV_VARS",sizeof("HTTP_ENV_VARS"),1

},

{

"_FILES",sizeof("_FILES"),"HTTP_POST_FILES",sizeof("HTTP_POST_FILES"),0

},

};

size_t

num_track_vars=sizeof(auto_global_records)/sizeof(struct

auto_global_record);

size_t

i;

/* jit_initialization = 0; */

for

(i=0;i<num_track_vars;i++)

{

PG(http_globals)[i]=NULL;

}

for

(p=PG(variables_order);p&& *p;p++)

{

switch(*p)

{

case

'p':

case

'P':

if

(!_gpc_flags[0]&& !SG(headers_sent)&&SG(request_info).request_method&& !strcasecmp(SG(request_info).request_method,"POST"))

{

sapi_module.treat_data(PARSE_POST,NULL,NULL

TSRMLS_CC); /* POST Data */

_gpc_flags[0]=1;

if

(PG(register_globals))

{

php_autoglobal_merge(&EG(symbol_table),Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST])

TSRMLS_CC);

}

}

break;

....以下省略,www.devdao.com:

}}}

到了这里说个题外话, 就是在php.ini中, 可以使用variables_order来控制PHP是否生成某个大变量,已经大变量的生成顺序。

关于顺序,就是说, 如果打开了auto_register_globals的情况下, 如果先处理p,后处理g,那么$_GET['a'],就会覆盖$_POST['a'];

可以看到,离成功不远了,sapi_module.treat_data 也就是php_default_treat_data,

在php_default_treat_data中,对于变量,都调用php_register_variable_safe来注册变量, 而php_register_variable_safe最终会调用php_register_variable_ex:

PHPAPI

void

php_register_variable_ex(char*var,zval*val,zval*track_vars_array

TSRMLS_DC)

{

char*p=NULL;

char*ip; /* index pointer */

char*index, *escaped_index=NULL;

int

var_len,index_len;

zval*gpc_element, **gpc_element_p;

zend_bool

is_array=0;

HashTable*symtable1=NULL;

assert(var!=NULL);

if

(track_vars_array)

{

symtable1=Z_ARRVAL_P(track_vars_array);

}

else

if

(PG(register_globals))

{

symtable1=EG(active_symbol_table);

}

if

(!symtable1)

{

/* Nothing to do */

zval_dtor(val);

return;

}

/*

* Prepare variable name

*/

/* ignore leading spaces in the variable name */

while

(*var&& *var=='

')

{

var++;

}

/* ensure that we don't have spaces or dots in the variable name (not binary safe) */

//特别注意以下这段。。。。

for

(p=var; *p;p++)

{

if

(*p=='

'|| *p=='.')

{

*p='_';

}

else

if

(*p=='[')

{

is_array=1;

ip=p;

*p=0;

break;

}

....以下省略

呵呵,问题的原因找到了, 就是在php_register_variable的时候,会将(.)转换成(_).

最后,再介绍下$_REQUEST变量的生成, 其实很简单, 在php_hash_environment中的最后, 会调用php_auto_globals_create_request(”_REQUEST”, sizeof(”_REQUEST”)-1TSRMLS_CC)来注册_REQUEST大变量, 在php_auto_globals_create_request(”_REQUEST”,sizeof(”_REQUEST”)-1 TSRMLS_CC)中,只是简单的将$_GET, $_POST, $_COOKIEmerge起来(G(http_globals)[TRACK_VARS_COOKIE]这部分,可以参看我较早前的在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究) :

static

zend_bool

php_auto_globals_create_request(char*name,uint

name_len

TSRMLS_DC)

{

zval*form_variables;

unsigned

char

_gpc_flags[3]={0,0,0};

char*p;

ALLOC_ZVAL(form_variables);

array_init(form_variables);

INIT_PZVAL(form_variables);

for

(p=PG(variables_order);p&& *p;p++)

{

switch

(*p)

{

case'g':

case'G':

if

(!_gpc_flags[0])

{

php_autoglobal_merge(Z_ARRVAL_P(form_variables),Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET])

TSRMLS_CC);

_gpc_flags[0]=1;

}

break; case'p':

case'P':

if

(!_gpc_flags[1])

{

php_autoglobal_merge(Z_ARRVAL_P(form_variables),Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST])

TSRMLS_CC);

_gpc_flags[1]=1;

}

break;

case'c':

case'C': if

(!_gpc_flags[2])

{

php_autoglobal_merge(Z_ARRVAL_P(form_variables),Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE])

TSRMLS_CC);

_gpc_flags[2]=1;

}

break;

}

}

zend_hash_update(&EG(symbol_table),"_REQUEST",sizeof("_REQUEST"), &form_variables,sizeof(zval*),NULL);

return

0;

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有