PHP Array Superscript type trap

Source: Internet
Author: User
Tags mongodb query
PHP array Subscript type trap

???? The project is developed using the PHP language, which uses MONGO DB storage; MONGO DB data is strongly typed, PHP data is weak type, in Friday I in MongoDB query a data always can not find, finally found the problem is the PHP array of numeric string subscript automatically turn into an integer subscript; so although PHP is a weakly typed language, We also want to pay attention to what types of variables are currently, familiar with PHP type automatic conversion rules, in some types of sensitive places to make type judgments or coercion type conversion.

??? The following example program simply explains this behavior:

?

$id = "", $arr 1[$id] = "xxx"; Var_dump ($arr 1); $id = $; $arr 2[$id] = "xxx"; Var_dump ($arr 2); $id = "022"; $arr 3[$id] = "xxx"; v Ar_dump ($arr 3); $id = "2222222222222"; $arr 4[$id] = "xxx"; Var_dump ($arr 4);

??? The output of this program is:

?

Array (1) {  [22]=>  string (3) "XXX"}array (1) {  [22]=>  string (3) "XXX"}array (1) {  ["022"]= >  String (3) "XXX"}array (1) {  ["2222222222222"]=>  string (3) "XXX"}
?

??? So, how is PHP's array string subscript type determined? Let's take a look at the source code in PHP.

??? First, we search in zend/zend_language_parser.y [, find the semantic parsing rules for arrays:

?

Object_dim_list:        object_dim_list ' [' dim_offset '] '  {fetch_array_dim (&$$, &$1, &$3 TSRMLS_CC);}                             |   Object_dim_list ' {' expr '} '        {fetch_string_offset (&$$, &$1, &$3 tsrmls_cc);}    |   variable_name {Znode tmp_znode;  Zend_do_pop_object (&tmp_znode tsrmls_cc);  Zend_do_fetch_property (&$$,  &tmp_znode, &$1 tsrmls_cc);}   ;

?

?? We are using arrays, so using the first rule Fetch_array_dim, in the Fetch_array_dim function, we find that the generated opcode is Zend_fetch_dim_w (84). In Zend/zend_vm_def.h, the ZEND_FETCH_DIM_W processing function zend_fetch_dimension_address processing to remove the subscript logic.

?

??? Continue to follow, from zend_fetch_dimension_address functions to Zend_fetch_dimension_address_inner, to Zend_symtable_update:

?

static inline int zend_symtable_update (HashTable *ht, char *arkey, uint nkeylength, void *pdata, uint ndatasize,  void **pdest)                 \{     handle_numeric (Arkey, Nkeylength, Zend_hash_index_update (HT, IDX, PData, Ndatasize, pDest));    Return Zend_hash_update (HT, Arkey, Nkeylength, PData, Ndatasize, pDest);                                      

?

?? Handle_numeric This macro is interesting, if the string subscript Arkey can be converted to a long integer idx, then call zend_hash_index_update to insert the data into the IDX position, otherwise call Zend_hash_ Update modifies the value of the Arkey location . Let's look at the specific definition of the macro:

?

#define HANDLE_NUMERIC (key, Length, func) {\ Register char *tmp=key;                                                                                        \ \ if (*tmp== '-') {\ t                                                                          mp++;  \} \ if ((*tmp>= ' 0 ' &&                                                         *tmp<= ' 9 ')) do {/* possibly a numeric index */\ char *end=key+length-1;                                                                       \ long idx; \ \ If (*tmp++== ' 0 ' &A mp;& length>2) {/* don ' t accept numbers with leading zeros */   \ break; \} \ while (TMP
 
  
= ' 0 ' && *tmp<= ' 9 ')} {\ break;                                                                           \            }                                                                      \ tmp++; \} \ if (Tmp==end &&                                                            *tmp== ' + ') {/* A numeric index */\ if (*key== '-') {                                            \ idx = strtol (key, NULL, 10);                                                         \ if (idx!=long_min) {\ return func;                                                                       \                }    \} else {                                                                \ idx = strtol (key, NULL, 10);                     \ if (Idx!=long_max) {\                                                        return func;                                                                           \                }                                                                       \            }                                                                               \        }                                                                        \} while (0); \}
 

??? from the macro we know the rules for the automatic conversion of string subscripts to Long integer subscripts:

??? 1. All numbers, but not leading 0, such as arkey= "0123" will not be converted to 123

??? 2. Cannot exceed the expression range of LONG (Long_min, Long_max), i.e. (-2147483648, 2147483647)

?

?

?

?

?

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.