程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP的GET/POST等大變量生成過程

PHP的GET/POST等大變量生成過程

編輯:關於PHP編程

· 作者: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 dont 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;
      &

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved