PHP in_array比较在不同的机器上的工作方式不同

时间:2013-02-11 12:03:06

标签: php arrays

请查看下面的代码,它会在不同的机器上显示不同的结果:

$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 个答案:

答案 0 :(得分:9)

非常简单....让我猜你的开发系统是windows,你的生产服务器是linux?

你有整数溢出问题,因为大多数人喜欢你的Windows版本的PHP是32位而linux是64位

See Condition for array key conversion

  • 包含有效整数的字符串将强制转换为整数类型。例如。键“8”实际上将存储在8下。另一方面,“08”将不会被强制转换,因为它不是有效的十进制整数。
  • 浮点数也会转换为整数,这意味着小数部分将被截断。例如。密钥8.7实际上将存储在8下。
  • Bool也会被转换为整数,即键值true实际上将存储在1下,键值为0表示错误。
  • Null将被强制转换为空字符串,即密钥null实际上将存储在“”下。 数组和对象不能用作键。这样做会导致警告:非法偏移类型。

所以会发生什么:

因此,28000000000000003上的密钥integer是有效的64bit,而String系统上的32bits是有效的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));

I was able to replicate your issue

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

Output

in_array

此问题与array_keys无关,而是与echo "<pre>"; $data = array("28000000000000003" => 'ABC',"28000000000000001" => 'PQR'); $keys = array("28000000000000003","28000000000000001"); $keysDerived = array_keys($data); var_dump($keys,$keysDerived); 示例

无关

Sample Code

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)
}

Output

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

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

See Online Demo

这意味着它们的类型不同......

  

in_array bool in_array(混合$ needle,数组$ haystack [,bool $ strict = FALSE])

     

如果第三个参数严格设置为 TRUE ,则in_array()函数还会检查大海捞针中的类型

If you run this code

string
string
integer
integer

Output 64位

string
string
string
string

输出32位

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));

Simple Workaround

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)

Output

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

See Original Code See Modified Code

使用的功能

{{1}}

答案 1 :(得分: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

答案 2 :(得分:2)

您可以尝试使用array_key_exists()。关联数组键的长度有一些限制。请参阅链接了解详情帮助PHP associative array's keys (indexes) limitations?

您可以增加密钥记忆限制。使用ini_set('memory_limit', '1024M');

答案 3 :(得分:2)

问题:如果你有长整数的键,例如'329462291595',它们在64位系统上将被视为本身,但它将是类型32位系统上的字符串

因此函数array_keys($data)将在64位系统中返回int,在32位系统中返回字符串

解决方案:将所有array_keys($data)转换为字符串。            然后in_array("28000000000000003",array_keys($data),true);使用第三个参数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严格检查