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

HRK*_*HRK 11 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"));
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,我们本地服务器上的所有4个案例的结果都是真的,而在第一个案例的生产服务器上,它给出了错误的结果

谁能帮我理解到底发生了什么?从配置的角度来看,我是否错过了?

Bab*_*aba 9

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

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

请参阅数组键转换的条件

  • 包含有效整数的字符串将强制转换为整数类型.例如,键"8"实际上将存储在8下.另一方面,"08"将不会被转换,因为它不是有效的十进制整数.
  • 浮点数也会转换为整数,这意味着小数部分将被截断.例如,密钥8.7实际上将存储在8下.
  • Bool也会被转换为整数,即键值true实际上将存储在1下,键值false则在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));
Run Code Online (Sandbox Code Playgroud)

产量

bool(false)    <----------------------- false instead of true 
bool(true)
bool(true)
bool(true)
Run Code Online (Sandbox Code Playgroud)

这个问题与例子无关,in_array而是一个array_keys例子

示例代码

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

产量

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)
}
Run Code Online (Sandbox Code Playgroud)

参见在线演示

这意味着它们不是同一类型......

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

如果第三个参数strict设置为TRUE,那么in_array()函数也将检查haystack中针类型.

如果您运行此代码

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

foreach ( $keysDerived as $key ) {
    echo gettype($key) . "\n";
}
Run Code Online (Sandbox Code Playgroud)

输出 64位

string
string
integer
integer
Run Code Online (Sandbox Code Playgroud)

输出32位

string
string
string
string
Run Code Online (Sandbox Code Playgroud)

简单的解决方法

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));
Run Code Online (Sandbox Code Playgroud)

产量

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)
Run Code Online (Sandbox Code Playgroud)

参见原始代码 请参见修改后的代

使用的功能

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


小智 6

您的本地服务器是32位,生产服务器是64位.

PHP文档说,在定义数组文字时,将转换键:

包含有效整数的字符串将强制转换为整数类型.例如,键"8"实际上将存储在8下.

所以,如果您尝试以下代码:

var_export(array("5" => "test"));
Run Code Online (Sandbox Code Playgroud)

您将看到结果是带有数字键的数组5,而不是字符串键"5".

在您的情况下,您有大型数字字符串作为键.在32位计算机上,数字28000000000000003超过了最大可能的整数值(PHP_INT_MAX),因此数组键将保持字符串,这就是本地服务器上发生的情况.另一方面,在64位计算机上,最大整数更大,并且"28000000000000003"被强制转换integer,这就是生产服务器上发生的情况.

因此,在64位生产服务器上运行时,array_keys($data)返回整数数组.在第一个测试用例中,您尝试使用严格比较在其中找到一个字符串FALSE.