程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> PHP編程中的變量生存周期

PHP編程中的變量生存周期

編輯:PHP綜合

對於PHP的中的數據來源, 不外乎有倆種:

  1. 1. 來自代碼中

對於代碼中的變量(也就是直接量)來說, 變量分配/賦值在編譯期, 活躍在執行器, 在請求關閉期被銷毀.對於這些變量來說, 使用APC進行Opcode緩存, 則會緩存這部分變量的值.

而對於來自外部的變量, 變量分配/賦值在編譯器後, 執行期前, 在請求關閉期被銷毀,對於這些變量來說, 使用APC進行OpCode緩存, 是不會被緩存的.

今天就著重關注下外部變量的一個部分,GET來的數據的整個生命周期.

假設, 有如下請求到來:

     

而, 在index.PHP中:

  1. <?PHP
  2.      $name      =

    對於PHP的中的數據來源, 不外乎有倆種:

    1. 1. 來自代碼中

    對於代碼中的變量(也就是直接量)來說, 變量分配/賦值在編譯期, 活躍在執行器, 在請求關閉期被銷毀.對於這些變量來說, 使用APC進行Opcode緩存, 則會緩存這部分變量的值.

    而對於來自外部的變量, 變量分配/賦值在編譯器後, 執行期前, 在請求關閉期被銷毀,對於這些變量來說, 使用APC進行OpCode緩存, 是不會被緩存的.

    今天就著重關注下外部變量的一個部分,GET來的數據的整個生命周期.

    假設, 有如下請求到來:

       

    而, 在index.PHP中:

    ___FCKpd___2

    我們知道, 在最後的執行期, $_GET數組必然包含如下片段:

    1.      

      對於PHP的中的數據來源, 不外乎有倆種:

      1. 1. 來自代碼中

      對於代碼中的變量(也就是直接量)來說, 變量分配/賦值在編譯期, 活躍在執行器, 在請求關閉期被銷毀.對於這些變量來說, 使用APC進行Opcode緩存, 則會緩存這部分變量的值.

      而對於來自外部的變量, 變量分配/賦值在編譯器後, 執行期前, 在請求關閉期被銷毀,對於這些變量來說, 使用APC進行OpCode緩存, 是不會被緩存的.

      今天就著重關注下外部變量的一個部分,GET來的數據的整個生命周期.

      假設, 有如下請求到來:

         

      而, 在index.PHP中:

      1. <?PHP
      2.      $name      =

        對於PHP的中的數據來源, 不外乎有倆種:

        1. 1. 來自代碼中

        對於代碼中的變量(也就是直接量)來說, 變量分配/賦值在編譯期, 活躍在執行器, 在請求關閉期被銷毀.對於這些變量來說, 使用APC進行Opcode緩存, 則會緩存這部分變量的值.

        而對於來自外部的變量, 變量分配/賦值在編譯器後, 執行期前, 在請求關閉期被銷毀,對於這些變量來說, 使用APC進行OpCode緩存, 是不會被緩存的.

        今天就著重關注下外部變量的一個部分,GET來的數據的整個生命周期.

        假設, 有如下請求到來:

           

        而, 在index.PHP中:

        ___FCKpd___2

        我們知道, 在最後的執行期, $_GET數組必然包含如下片段:

        ___FCKpd___3

        那麼, 我們今天就重點關注下, Query String是如何構建成_GET數組的(關於GET變量的生成, 請一並閱讀我之前的文章: “PHP的GET/POST等大變量生成過程“):

        在請求到來時刻,PHP_request_startup(定義在main.c)被調用,來做初始化現場. 在這個過程中包括設置超時值,調用各個模塊的請求初始化函數. 當然也包括我們關心的, 創建變量環境.

        php_hash_environment根據PHP.ini中的variables_order來依次初始化各個預定義大變量, 那麼對於$_GET來說:

        1. ...
        2. case 'g':
        3. case 'G':
        4.      if (!_gpc_flags[2]) {
        5.           sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC);
        6.           _gpc_flags[2] = 1;
        7.           if (PG(register_globals)) {
        8.                PHP_autoglobal_merge(&EG(symbol_table),
        9.                     Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]) TSRMLS_CC);
        10.           }
        11.      }
        12. break;

        大體可以看出,這段邏輯,首先通過treat_data來生成變量hash(PG(http_globals)[TRACK_VARS_GET]), 如果打開了auto_register_globals,則再把$_GET數組中的變量加入到符號表中.

        treat_data是屬於sapi_module_struct中的一個成員:

        1.  注意:     本文基於apache2handler方式的sapi, 這個啟動過程和之前的文章sapi
        2. 原理中的啟動過程略有不同, PHP5通過注冊apache2的ap_hook_post_config掛鉤,
        3. 在apache server啟動的時候啟動PHP(PHP_apache_server_startup,定義在
        4. sapi/apache2hander/sapi_apache2.c中), 在這個函數中調用sapi_startup啟動sapi,
        5. 繼而通過調用PHP_apache2_startup來注冊sapi module struct,
        6. 然後調用php_module_startup來初始化PHP, 其中又會初始化ZEND引擎,
        7. 以及填充zend_module_struct中的treat_data成員(通過PHP_startup_sapi_content_types)

        現在回過頭來繼續看treat_data(也就是PHP_default_treat_data):

        1. ....
        2. if (arg == PARSE_GET) { /* GET data */
        3.      c_var = SG(request_info).query_string;
        4.      if (c_var && *c_var) {
        5.           res = (char *) estrdup(c_var);
        6.           free_buffer = 1;
        7.      } else {
        8.           free_buffer = 0;
        9.      }
        10. } else if (arg == PARSE_COOKIE) { /* CookIE data */

        在上面的邏輯中, 給res復制為query_string, SG(request_info)是一個代表了當前請求信息的結構體, 其中query_string是在PHP_apache_request_ctor中通過復制apache的reqeust_rec結構體中的args而來的.

        對於本文的例子來說, 此時res即為”name=laruence&career[]=yahoo&career[]=baidu”,

        繼續在treat_data中, 隨後的邏輯是:

        1. var = PHP_strtok_r(res, separator, &strtok_buf);
        2. ...
        3. while (var) {
        4.      val = strchr(var, '=');
        5.  
        6.      if (arg == PARSE_COOKIE) {
        7.           /* Remove leading spaces from cookIE names,
        8.                needed for multi-cookIE header where ; can be followed by a space */
        9.           while (isspace(*var)) {
        10.                var++;
        11.           }
        12.           if (var == val || *var == '\0') {
        13.                goto next_cookIE;
        14.           }
        15.      }
        16.  
        17.      if (val) { /* have a value */
        18.           int val_len;
        19.           unsigned int new_val_len;
        20.  
        21.           *val++ = '\0';
        22.           PHP_url_decode(var, strlen(var));
        23.           val_len = PHP_url_decode(val, strlen(val));
        24.           val = estrndup(val, val_len);
        25.           if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
        26.                PHP_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
        27.           }
        28.           efree(val);
        29.      } else {

        首先, 通過php_strtok_r把res根據”&”分割成一個一個的”key=value”段, 接下來分別為var和val復制為key和value, 注意到這個過程中會分別對var和val做PHP_url_decode.

        最後通過PHP_register_variable_safe, 給array_ptr(此時指向PG(http_globals)[TRACK_VARS_GET], 也就是$_GET)添加一個名為var值為val的成員.

        到了這一步, 我們的$_GET數組中, 就包含了如下的成員:

        1. 'name' => 'laruence',
        2. 'career' => array(
        3.      'yahoo', 'baidu',

        未完待續(變量的銷毀過程)…

        GET['name'];

      我們知道, 在最後的執行期, $_GET數組必然包含如下片段:

      ___FCKpd___3

      那麼, 我們今天就重點關注下, Query String是如何構建成_GET數組的(關於GET變量的生成, 請一並閱讀我之前的文章: “PHP的GET/POST等大變量生成過程“):

      在請求到來時刻,PHP_request_startup(定義在main.c)被調用,來做初始化現場. 在這個過程中包括設置超時值,調用各個模塊的請求初始化函數. 當然也包括我們關心的, 創建變量環境.

      php_hash_environment根據PHP.ini中的variables_order來依次初始化各個預定義大變量, 那麼對於$_GET來說:

      ___FCKpd___4

      大體可以看出,這段邏輯,首先通過treat_data來生成變量hash(PG(http_globals)[TRACK_VARS_GET]), 如果打開了auto_register_globals,則再把$_GET數組中的變量加入到符號表中.

      treat_data是屬於sapi_module_struct中的一個成員:

      ___FCKpd___5

      現在回過頭來繼續看treat_data(也就是PHP_default_treat_data):

      ___FCKpd___6

      在上面的邏輯中, 給res復制為query_string, SG(request_info)是一個代表了當前請求信息的結構體, 其中query_string是在PHP_apache_request_ctor中通過復制apache的reqeust_rec結構體中的args而來的.

      對於本文的例子來說, 此時res即為”name=laruence&career[]=yahoo&career[]=baidu”,

      繼續在treat_data中, 隨後的邏輯是:

      ___FCKpd___7

      首先, 通過php_strtok_r把res根據”&”分割成一個一個的”key=value”段, 接下來分別為var和val復制為key和value, 注意到這個過程中會分別對var和val做PHP_url_decode.

      最後通過PHP_register_variable_safe, 給array_ptr(此時指向PG(http_globals)[TRACK_VARS_GET], 也就是$_GET)添加一個名為var值為val的成員.

      到了這一步, 我們的$_GET數組中, 就包含了如下的成員:

      ___FCKpd___8

      未完待續(變量的銷毀過程)…

      GET = array(
    2.           'name' => 'laruence',
    3.           'career' => array(
    4.                'yahoo', 'baidu',
    5.           ),

    那麼, 我們今天就重點關注下, Query String是如何構建成_GET數組的(關於GET變量的生成, 請一並閱讀我之前的文章: “PHP的GET/POST等大變量生成過程“):

    在請求到來時刻,PHP_request_startup(定義在main.c)被調用,來做初始化現場. 在這個過程中包括設置超時值,調用各個模塊的請求初始化函數. 當然也包括我們關心的, 創建變量環境.

    php_hash_environment根據PHP.ini中的variables_order來依次初始化各個預定義大變量, 那麼對於$_GET來說:

    ___FCKpd___4

    大體可以看出,這段邏輯,首先通過treat_data來生成變量hash(PG(http_globals)[TRACK_VARS_GET]), 如果打開了auto_register_globals,則再把$_GET數組中的變量加入到符號表中.

    treat_data是屬於sapi_module_struct中的一個成員:

    ___FCKpd___5

    現在回過頭來繼續看treat_data(也就是PHP_default_treat_data):

    ___FCKpd___6

    在上面的邏輯中, 給res復制為query_string, SG(request_info)是一個代表了當前請求信息的結構體, 其中query_string是在PHP_apache_request_ctor中通過復制apache的reqeust_rec結構體中的args而來的.

    對於本文的例子來說, 此時res即為”name=laruence&career[]=yahoo&career[]=baidu”,

    繼續在treat_data中, 隨後的邏輯是:

    ___FCKpd___7

    首先, 通過php_strtok_r把res根據”&”分割成一個一個的”key=value”段, 接下來分別為var和val復制為key和value, 注意到這個過程中會分別對var和val做PHP_url_decode.

    最後通過PHP_register_variable_safe, 給array_ptr(此時指向PG(http_globals)[TRACK_VARS_GET], 也就是$_GET)添加一個名為var值為val的成員.

    到了這一步, 我們的$_GET數組中, 就包含了如下的成員:

    ___FCKpd___8

    未完待續(變量的銷毀過程)…

    GET['name'];

我們知道, 在最後的執行期, $_GET數組必然包含如下片段:

___FCKpd___3

那麼, 我們今天就重點關注下, Query String是如何構建成_GET數組的(關於GET變量的生成, 請一並閱讀我之前的文章: “PHP的GET/POST等大變量生成過程“):

在請求到來時刻,PHP_request_startup(定義在main.c)被調用,來做初始化現場. 在這個過程中包括設置超時值,調用各個模塊的請求初始化函數. 當然也包括我們關心的, 創建變量環境.

php_hash_environment根據PHP.ini中的variables_order來依次初始化各個預定義大變量, 那麼對於$_GET來說:

___FCKpd___4

大體可以看出,這段邏輯,首先通過treat_data來生成變量hash(PG(http_globals)[TRACK_VARS_GET]), 如果打開了auto_register_globals,則再把$_GET數組中的變量加入到符號表中.

treat_data是屬於sapi_module_struct中的一個成員:

___FCKpd___5

現在回過頭來繼續看treat_data(也就是PHP_default_treat_data):

___FCKpd___6

在上面的邏輯中, 給res復制為query_string, SG(request_info)是一個代表了當前請求信息的結構體, 其中query_string是在PHP_apache_request_ctor中通過復制apache的reqeust_rec結構體中的args而來的.

對於本文的例子來說, 此時res即為”name=laruence&career[]=yahoo&career[]=baidu”,

繼續在treat_data中, 隨後的邏輯是:

___FCKpd___7

首先, 通過php_strtok_r把res根據”&”分割成一個一個的”key=value”段, 接下來分別為var和val復制為key和value, 注意到這個過程中會分別對var和val做PHP_url_decode.

最後通過PHP_register_variable_safe, 給array_ptr(此時指向PG(http_globals)[TRACK_VARS_GET], 也就是$_GET)添加一個名為var值為val的成員.

到了這一步, 我們的$_GET數組中, 就包含了如下的成員:

___FCKpd___8

未完待續(變量的銷毀過程)…

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