2013-02-11 95 views
11

請仔細閱讀下面這段代碼,它給在不同機器上不同的結果:PHP in_array比較不同的機器上不同工作

$data = array(
    "28000000000000003" => 'ABC', 
    "28000000000000001" => 'PQR' 
); 

echo "1.".in_array("28000000000000003",array_keys($data),true); 

echo "2.".in_array("28000000000000003",array_keys($data)); 

echo "3.".in_array("28000000000000003",array("28000000000000003","28000000000000001"),true); 

echo "4.".in_array("28000000000000003",array("28000000000000003","28000000000000001")); 

正如預期的那樣,所有4種情況下,我們本地服務器上產生真正的,而在生產服務器在第一種情況下給出了錯誤的結果,並在其餘三個中爲真

任何人都可以幫助我理解究竟發生了什麼嗎?我從配置的角度錯過了嗎?

+4

你絕對清楚的是,這些都是字符串? – jeroenvisser101 2013-02-11 12:07:58

+0

沒有任何意義。 – Shoe 2013-02-11 12:08:08

+0

如果這個數字是*不是*字符串,但是整數將會給出不同的結果 – 2013-02-11 12:09:34

回答

9

它很容易....讓我猜你的開發系統是Windows,你的生產服務器是Linux?

你有整數溢出問題,因爲大多數LIKEY您的Windows版本的PHP是32位,而Linux是64位

See Condition for array key conversion

  • 包含有效整數的字符串將被強制轉換爲整數類型。例如。鍵「8」實際上將被存儲在8以下。另一方面,「08」不會被轉換,因爲它不是有效的十進制整數。
  • 浮點數也被轉換爲整數,這意味着小數部分將被截斷。例如。鍵8.7實際上將被存儲在8以下。
  • Bools也被轉換爲整數,也就是說,關鍵字true將被實際存儲在1以下並且關鍵字false被置於0以下。
  • Null將被轉換爲空字符串,即密鑰null實際上將被存儲在「」之下。 數組和對象不能用作鍵。這樣做會導致警告:非法偏移類型。

所以會發生什麼是:

所以關鍵28000000000000003是一個64bit有效integer32bits系統

I was able to replicate your issue

echo "<pre>"; 
$data = array("28000000000000003" => 'ABC',"28000000000000001" => 'PQR'); 
$keys = array("28000000000000003","28000000000000001"); 
$keysDerived = array_keys($data); 

var_dump(in_array("28000000000000003", $keysDerived, true)); 
var_dump(in_array("28000000000000003", $keysDerived)); 
var_dump(in_array("28000000000000003", $keys, true)); 
var_dump(in_array("28000000000000003", $keys)); 

Output

String
bool(false) <----------------------- false instead of true 
bool(true) 
bool(true) 
bool(true) 

這個問題有沒有關係in_array而是array_keys例如

Sample Code

echo "<pre>"; 
$data = array("28000000000000003" => 'ABC',"28000000000000001" => 'PQR'); 
$keys = array("28000000000000003","28000000000000001"); 
$keysDerived = array_keys($data); 
var_dump($keys,$keysDerived); 

Output

array(2) { 
    [0]=> 
    string(17) "28000000000000003" <------- Keys are String 
    [1]=> 
    string(17) "28000000000000001" 
} 
array(2) { 
    [0]=> 
    int(28000000000000003)   <------- They are converted to int on 64bits 
    [1]=> 
    int(28000000000000001) 
} 

See Online Demo

這意味着他們不是同一類型...

in_array布爾in_array(混合$針,數組$草堆[,布爾$嚴格= FALSE])

如果第三個參數嚴格設置爲TRUE則in_array()函數將還請檢查乾草堆中針的類型。

If you run this code

foreach ($keys as $key) { 
    echo gettype($key) . "\n"; 
} 

foreach ($keysDerived as $key) { 
    echo gettype($key) . "\n"; 
} 

Output 64bits的

string 
string 
integer 
integer 

輸出32位

string 
string 
string 
string 

Simple Workaround

echo "<pre>"; 
$data = array("28000000000000003" => 'ABC',"28000000000000001" => 'PQR'); 
$keys = array("28000000000000003","28000000000000001"); 
$keysDerived = array_keys_string($data); 
var_dump($keys,$keysDerived); 

var_dump(in_array("28000000000000003", $keysDerived, true)); 
var_dump(in_array("28000000000000003", $keysDerived)); 
var_dump(in_array("28000000000000003", $keys, true)); 
var_dump(in_array("28000000000000003", $keys)); 

Output

array(2) { 
    [0]=> 
    string(17) "28000000000000003" 
    [1]=> 
    string(17) "28000000000000001" 
} 
array(2) { 
    [0]=> 
    string(17) "28000000000000003" 
    [1]=> 
    string(17) "28000000000000001" 
} 
bool(true) 
bool(true) 
bool(true) 
bool(true) 

See Original Code See Modified Code

功能用於

function array_keys_string(array $input) { 
    $list = array(); 
    foreach ($input as $k => $v) { 
     $list[] = (string)$k; 
    } 
    return $list; 
} 
2

您可以嘗試使用array_key_exists()。關聯數組鍵的長度有一些限制。請參閱鏈接以獲取詳細信息幫助PHP associative array's keys (indexes) limitations?

您可以增加您的密鑰內存限制。使用ini_set('memory_limit', '1024M');

+0

他的問題中沒有任何內容描述任何可能會觸發內存限制的行爲。另外,在大事情中,他的數組鍵很短。這個答案似乎沒有解決他的問題。 – Corbin 2013-02-11 13:09:20

2

問題:如果你有一個長整型鍵,如「329462291595」,他們將被視爲爲64位系統中,例如,但將類型的上一個32位系統。轉換所有array_keys($data)到字符串:

因此函數array_keys($data)將在32位系統

解決方案在64位系統和字符串返回INT。 再與第三個參數true(嚴格檢查)in_array("28000000000000003",array_keys($data),true);

function array_keys_string($arr){ 
    $arr_keys  = array_keys($arr); 
    $res_arry  = array(); 
    foreach($arr_keys as $val){ 
     $res_arry[] = (string)$val; 
    } 
    return $res_arry; 
} 


echo "1.".in_array("28000000000000003",array_keys_string($data),true); 

這會給你在這兩個服務器相同的結果。

請參考以下鏈接

裁判:http://www.php.net/manual/en/function.array-keys.php#105578

從php.net:http://www.php.net/manual/en/function.in-array.php

<?php 
$a = array('1.10', 12.4, 1.13); 

if (in_array('12.4', $a, true)) { 
    echo "'12.4' found with strict check\n"; 
} 

if (in_array(1.13, $a, true)) { 
    echo "1.13 found with strict check\n"; 
} 
?> 

上面的例子將輸出:嚴格檢查發現1.13

+1

不可以。在32位平臺上,'array_keys($ data)'將包含字符串,而不包含引號的'28000000000000003' [將被轉換爲浮點](http://php.net/manual/en/language.types .integer.php#language.types.integer.overflow),所以'in_array'的結果是'FALSE'。 – 2013-02-11 13:42:31

6

你本地服務器是32位,您的生產服務器是64位。

PHP documentation說,限定數組文本時,鍵將被投:

含有有效整數字符串將被強制轉換爲整數類型。例如。鍵「8」,實際上在8

儲存所以,如果你嘗試下面的代碼:

var_export(array("5" => "test")); 

你會看到結果與數字鍵5一個數組,而不是字符串鍵"5"

在你的情況下,你有大數字字符串作爲鍵。在32位機器上,編號28000000000000003超過了最大可能的整數值(PHP_INT_MAX),因此數組鍵將保持字符串,這就是您的本地服務器上發生的情況。另一方面,在64位機器上,最大整數的方式更大,並且"28000000000000003"轉換爲integer,這就是生產服務器上發生的情況。

因此,在64位生產服務器上運行時,array_keys($data)會返回整數數組。在第一個測試用例中,當您嘗試使用嚴格比較在其中查找字符串時,會得到FALSE