10
$arrValue = array('first', 'second');
$ret = in_array(0, $arrValue);
var_dump($ret);
var_dump($arrValue);

Above example gives following result:

bool(true)
array(2) {
  [0]=> string(5) "first"
  [1]=> string(6) "second"
}

Why in_array() matches needle 0 to any given haystack?

Rizier123
  • 58,877
  • 16
  • 101
  • 156
Index
  • 676
  • 1
  • 10
  • 27
  • 3
    See the first comment here: http://nl1.php.net/in_array Add a third parameter `true` in the `in_array` function to set the checking to strict. – KrekkieD May 19 '14 at 10:46
  • 0 == 'first'; 0 !== 'first'; – Deadooshka May 19 '14 at 10:48
  • You pretty much have to use strict equality with in_array, is the conclusion I've come to, or you'll have situation like this: echo in_array('test',['fail' => true]) ? 'WHOOPS' : '' – 111 Jan 14 '20 at 05:37

2 Answers2

21

That's because the function uses a non-strict comparison. The string in the array is compared to integer 0. Some typecasting is happening with data loss, and both are regarded the same:

var_dump(0 == 'first'); //  bool(true)

So solve this, you can use the third parameter and set it to true to request strict comparison.

$ret = in_array(0, $arrValue, true);

Keep in mind, through, that strict is really strict. In a strict comparison, 0 is not equal to "0".

Docs: http://nl3.php.net/in_array

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
  • 7
    So `0 == 'first'` got to love PHP. – Loïc May 19 '14 at 10:48
  • can you tell which casts actually make 0 == 'first', thanks – fast May 19 '14 at 10:50
  • 1
    @Loïc: [this](https://eval.in/111886) or [this](http://3v4l.org/a0nKq) is even better. – DCoder May 19 '14 at 10:50
  • 1
    Yeah, you would expect `0` to be typecasted to `"0"`, instead of `"first"` being typecasted to `0`, but that's not how it works. Actually, we should be lucky that `"first"` isn't typecasted to `"1"` and `"second"` to `2`. ;) – GolezTrol May 19 '14 at 10:51
  • @fast That's a typecast inside the `in_array` function, not one in the code in the question. – GolezTrol May 19 '14 at 10:52
  • 1
    yes, was just a side question.. (so (int) string == 0; ok..) thx :-) – fast May 19 '14 at 10:53
  • 1
    @DCoder I don't get it! when I change one of the string hashed, I don't get the `true` anymore, what is that black magic? – Loïc May 19 '14 at 10:57
  • 1
    @Loic: it might be treated as numbers: "0e..." – fast May 19 '14 at 11:01
  • @fast so that would mean, whenever one would use `$a == $b` php interpreter would do `(int) $a === (int) $b` ?? – Loïc May 19 '14 at 11:02
  • 1
    @Loïc No, only if one of them is an int. If both are strings, then the comparison uses them as-is. – GolezTrol May 19 '14 at 11:03
  • 1
    @Loïc: fast is correct. PHP tries **really hard** to treat a string as a number - it supports exponential notation (`"1e2" == "100"`), octal and hex (`"0xff" == "255"`), floats (`"255.0" == "255"`)... Check out [r/lolphp](http://www.reddit.com/r/lolphp/) for more nightmare fuel. The md5 thing I posted is indeed exponentials, like fast said - they both start with `0e` and contain only digits after that. – DCoder May 19 '14 at 11:05
  • 3
    Check out [PHP, a fractal of bad design](http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/) for more nightmare fuel.:) – GolezTrol May 19 '14 at 11:11
  • @GolezTrol : PHP is very Idiotic .isn't it ? – Alireza Fallah May 19 '14 at 11:34
0

Basically here 0 treats as false, so the search will occur like the function in_array search false between your array value. Make it(0) string to get different output. As php a support strict or non-strict comparison so you need to pass a third value true it tell the to be strict because by default it is non-strict.

biswajitGhosh
  • 147
  • 1
  • 2
  • 17