You already have answers that will tell you how to get around this. Let me just add a more technical answer why this is happening ....
This behavior is rooted in a peculiar way ZEND_API int compare_function(..) . When you call in_array(needle, haystack, strict) without $ strict = true, this function is used to compare needle with each element in the haystack until a match is found.
Your needle is a string, and the elements in the haystack are integers.
Let's take a (n shorthand) look at compare_function()
while(1) { switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { case TYPE_PAIR(IS_LONG, IS_LONG): ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0)); return SUCCESS; [...more CASEs that don't apply on the first iteration of the while-loop...] default: [...some if-elseif cases that do not apply on the first iteration of the while-loop...] } else { zendi_convert_scalar_to_number(op1, op1_copy, result); zendi_convert_scalar_to_number(op2, op2_copy, result); converted = 1; } [...]
when this code is called for the first time, op1 ~ 'test' and op2~0 . (~ means “roughly”, because internal representation is a little different, but it doesn't really matter.)
But there is no case for TYPE_PAIR (IS_STRING, IS_LONG), so it falls into the default branch :. There are some if-conditions for processing objects, but none of them is an object, so it falls into the part where the operands are converted (once). Again, if-conditon is applied, so it falls into the last else branch, which converts both operands to numbers.
'test' converted to 0 and 0 remains 0 .
Then the while loop executes again, now with TYPE_PAIR (IS_LONG, IS_LONG) - the very first case. And now both operands are equal -> in_array () returns true.
... and yes, I also embarrass this; -)
source share