このプロジェクトは、MONGO DB ストレージを使用する PHP 言語を使用して開発されています。MONGO DB のデータは強い型であり、PHP のデータは弱い型です。先週の金曜日、ついに、MONGODB でデータ クエリが見つかりませんでした。問題は、PHP 配列の数値文字列の添字が自動的に整数の添字に変換されることであることがわかりました。したがって、PHP は型指定が弱い言語ですが、変数の現在の型にも注意し、PHP の自動関数についても理解しておく必要があります。型変換ルール。型に依存する場所では、型判定または強制型変換を実行します。
次のプログラム例は、この現象を簡単に説明しています:
PHPコード
$id = "22";
$arr1[$id] = "xxx";
var_dump($arr1);
$id = 22;
$arr2[$id] = "xxx";
var_dump($arr2);
$id = "022";
$arr3[$id] = "xxx";
var_dump($arr3);
$id = "2222222222222";
$arr4[$id] = "xxx";
var_dump($arr4);
$id = "22";$arr1[$id] = "xxx";var_dump($arr1);$id = 22;$arr2[$id] = "xxx";var_dump($arr2);$id = " 022";$arr3[$id] = "xxx";var_dump($arr3);$id = "2222222222222";$arr4[$id] = "xxx";var_dump($arr4);
このプログラムの出力は次のとおりです:
PHPコード
配列(1) {
[22]=>
文字列(3) "xxx"
}
配列(1) {
[22]=>
文字列(3) "xxx"
}
配列(1) {
["022"]=>
文字列(3) "xxx"
}
配列(1) {
["2222222222222"]=>
文字列(3) "xxx"
}
配列(1) { [22]=> 文字列(3) "xxx"}配列(1) { [22]=> 文字列(3) "xxx"}配列(1) { ["022"]=> ; 文字列(3) "xxx"}配列(1) { ["2222222222222"]=> 文字列(3) "xxx"}
では、PHP の配列文字列の添字タイプはどのように決定されるのでしょうか? PHPのソースコードを見てみましょう。
まず、Zend/zend_ language_parser.y で [ を検索して、配列の意味解析ルールを見つけます。
PHPコード
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);
| 変数名 { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC);}
;
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); | 変数名 { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC);} ;
配列を使用しているので、最初のルール fetch_array_dim を使用します。 fetch_array_dim 関数では、生成されたオペコードが ZEND_FETCH_DIM_W(84) であることがわかります。 Zend/zend_vm_def.h では、zend_fetch_dimension_address が ZEND_FETCH_DIM_W 処理関数の記述子ロジックを処理します。
引き続き、zend_fetch_dimension_address 関数から zend_fetch_dimension_address_inner、そして zend_symtable_update に進みます。
PHPコード
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));
zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest) を返します。
}
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) );ハッシュ_アップデート(ht、arKey、nKeyLength、pData、nDataSize、pDest);
HANDLE_NUMERIC マクロは非常に興味深いもので、文字列添字 arKey を長整数 idx に変換できる場合は、zend_hash_index_update を呼び出してデータを idx 位置に挿入し、それ以外の場合は zend_hash_update を呼び出して arKey 位置の値を変更します。マクロの具体的な定義を見てみましょう:
PHPコード
#define HANDLE_NUMERIC(key, length, func) {
char *tmp=key; を登録します。
if (*tmp=='-') {
tmp++;
If ((*tmp>='0' && *tmp
長い IDX;
if (*tmp++=='0' && length>2) { /* 先頭にゼロが付いた数字は受け入れられません */
壊す;
}
while (tmp
壊す;
}
tmp++;
}
if (tmp==end && *tmp==' ') { /* 数値インデックス */
if (*key=='-') {
idx = strtol(キー, NULL, 10);
if (idx!=LONG_MIN) {
戻り関数;
}
} else {
idx = strtol(キー, NULL, 10);
if (idx!=LONG_MAX) {
戻り関数;
}
}
}
一方 (0);
}
#define HANDLE_NUMERIC(key, length, func) { register char *tmp=key; if (*tmp=='-') { tmp++; } if ((*tmp>='0' && *tmp<='9')) do { /* 数値インデックスの可能性があります */ char *end=key+length-1; 長い IDX; if (*tmp++=='0' && length>2) { /* 先頭にゼロが付いた数字は受け入れられません */ Break; } while (tmp
1. すべて数字ですが、前导0はできません、比arKey="0123"不会转化成123
2. 長さを超過できない表示范围(LONG_MIN, LONG_MAX)、すなわち(-2147483648, 2147483647)