ChrisW
ChrisW

Reputation: 5048

PHP's variable type leniency

The most recent comment on PHP's in_array() help page (http://uk.php.net/manual/en/function.in-array.php#106319) states that some unusual results occur as a result of PHP's 'leniency on variable types', but gives no explanation as to why these results occur. In particular, I don't follow why these happen:

// Example array

$array = array(
    'egg' => true,
    'cheese' => false,
    'hair' => 765,
    'goblins' => null,
    'ogres' => 'no ogres allowed in this array'
);

// Loose checking (this is the default, i.e. 3rd argument is false), return values are in comments
in_array(763, $array); // true
in_array('hhh', $array); // true

Or why the poster thought the following was strange behaviour

in_array('egg', $array); // true
in_array(array(), $array); // true

(surely 'egg' does occur in the array, and PHP doesn't care whether it's a key or value, and there is an array, and PHP doesn't care if it's empty or not?)

Can anyone give any pointers?

Upvotes: 5

Views: 225

Answers (3)

Esailija
Esailija

Reputation: 140244

PHP treating arrays as primitive values is a constant source of pain as they can be very complex data structures, it doesn't make any sense. For example, if you assign array to something, and then modify the array, the original isn't modified, instead it is copied.

<?php

$arr = array(
    "key" => NULL
);



var_dump( array() == NULL ); //True :(
var_dump( in_array( array(), $arr ) ); //True, wtf? It's because apparently array() == NULL
var_dump( in_array( new stdClass, $arr ) ); //False, thank god

?>

Also, 'egg' is not a value in the array, it's a key, so of course it's surprising that it would return true. This kind of behavior is not ok in any other language I know about, so it will trip over many people who don't know php quirks inside out.

Even a simple rule that an empty string is falsy, is violated in php:

if( "0" ) {
echo "hello"; //not executed
}

"0" is a non-empty string by any conceivable definition, yet it is a falsy value.

Upvotes: 1

Marc B
Marc B

Reputation: 360922

Internally, you can think of the basic in_array() call working like this:

function in_array($needle, $haystack, $strict = FALSE) {
    foreach ($haystack as $key => $value) {
        if ($strict === FALSE) {
            if ($value == $needle) {
                return($key);
            }
        } else {
            if ($value === $needle) {
                return($key);
        }
    }
    return(FALSE);
}

note that it's using the == comparison operator - this one allows typecasting. So if your array contains a simple boolean TRUE value, then essentially EVERYTHING your search for with in_array will be found, and almost everything EXCEPT the following in PHP can be typecast as true:

'' == TRUE // false
0 == TRUE // false
FALSE == TRUE // false
array() == TRUE // false
'0' == TRUE // false

but:

'a' == TRUE // true
1 == TRUE // true
'1' == TRUE // true
3.1415926 = TRUE // true
etc...

This is why in_array has the optional 3rd parameter to force a strict comparison. It simply makes in_array do a === strict comparison, instead of ==.

Which means that

'a' === TRUE // FALSE

Upvotes: 2

Mathieu Dumoulin
Mathieu Dumoulin

Reputation: 12244

763 == true because true equals anything not 0, NULL or '', same thing for array because it is a value (not an object).

To circumvent this problem you should pass the third argument as TRUE to be STRICT and thus, is_rray will do a === which is a type equality so then

763 !== true

and neither will array() !== true

Upvotes: 5

Related Questions