Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Please review following piece of code, it is giving different results on different machines:

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

As expected, results true for all 4 cases on our local server, while on production server in 1st case it is giving false result and true in rest of three

Can anybody help me to understand what exactly happening? Do I missed from configuration point of view?

share|improve this question
4  
Are you absolutely sure about the fact that these are strings? – jeroenvisser101 Feb 11 at 12:07
1  
do array_map('var_dump', array_keys($data)); – One Trick Pony Feb 11 at 12:10
3  
So there's your answer :) How are you creating that array on production? – One Trick Pony Feb 11 at 12:13
1  
Does the production machine use 64-bit version of PHP? – Salman A Feb 11 at 12:20
1  
it seems related to this, so use the 3rd argument on array_keys (strict) – One Trick Pony Feb 11 at 12:23
show 10 more comments

4 Answers

up vote 9 down vote accepted

Its very easy .... let me guess your Development system is windows and your production server is linux ?

You are having Integer overflow Issues because most likey your windows version of PHP is 32bit and linux is 64bit

See Condition for array key conversion

  • Strings containing valid integers will be cast to the integer type. E.g. the key "8" will actually be stored under 8. On the other hand "08" will not be cast, as it isn't a valid decimal integer.
  • Floats are also cast to integers, which means that the fractional part will be truncated. E.g. the key 8.7 will actually be stored under 8.
  • Bools are cast to integers, too, i.e. the key true will actually be stored under 1 and the key false under 0.
  • Null will be cast to the empty string, i.e. the key null will actually be stored under "". Arrays and objects can not be used as keys. Doing so will result in a warning: Illegal offset type.

So what happens is that :

So the key 28000000000000003 is a valid integer on a 64bit but a String on a 32bits system

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

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

This issues has nothing to do with in_array but rather array_keys example

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

This means that they are not the same type ...

in_array bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

If the third parameter strict is set to TRUE then the in_array() function will also check the types of the needle in the haystack.

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

Output 32Bits

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 Used

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

You can try using array_key_exists() . associative array keys has some limitation in length. see the link for details help PHP associative array's keys (indexes) limitations?

You can increase your key memory limit. use ini_set('memory_limit', '1024M');

share|improve this answer
Nothing in his question describes any behavior that would be indicative of hitting a memory limit. Additionally, in the big scheme of things, his array keys are relatively short. This answer doesn't seem to address his question. – Corbin Feb 11 at 13:09

Issue : If you have keys that are long integer, such as '329462291595', they will be considered as such on a 64bits system, but will be of type string on a 32 bits system.

So the function array_keys($data) will return int in 64 bit system and string in 32 bit system

Solution : convert all array_keys($data) to string. and then in_array("28000000000000003",array_keys($data),true); with third parameter true (for strict check)

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

this will give you same result in both the servers.

Refer following links :

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

From 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";
}
?>

The above example will output: 1.13 found with strict check

share|improve this answer
1  
No. On a 32-bit platform, array_keys($data) will contain strings, whilst 28000000000000003 without quotes will be converted to float, so the result of in_array with strict compatison will be FALSE. – Denys Popov Feb 11 at 13:42

Your local server is 32-bit and your production server is 64-bit.

PHP documentation says that when defining array literals, keys will be cast:

Strings containing valid integers will be cast to the integer type. E.g. the key "8" will actually be stored under 8.

So, if you try the following piece of code:

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

You will see the result is an array with numerical key 5, not string key "5".

In your case, you have large numerical strings as keys. On a 32-bit machine, number 28000000000000003 exceeds the maximum possible integer value (PHP_INT_MAX), so the array key will stay string, and that is what happens on your local server. On a 64-bit machine, on the other hand, maximum integer is way greater, and "28000000000000003" is cast to integer, and that is what happens on your production server.

So, when run on the 64-bit production server, array_keys($data) returns array of integers. When in your first test case you try to find a string in it using strict comparison, you get FALSE.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.