What is wrong with the PHP function in_array(...)? [duplicate] - php

This question already has answers here:
PHP in_array() / array_search() odd behaviour
(2 answers)
Closed 6 years ago.
The PHP function in_array(...) "checks if a value exists in an array".
But I'm observing a very strange behavior on handling strings (PHP v7.0.3). This code
$needle = 'a';
$haystacks = [['a'], ['b'], [123], [0]];
foreach ($haystacks as $haystack) {
$needleIsInHaystack = in_array($needle, $haystack);
var_dump($needleIsInHaystack);
}
generates following output:
bool(true)
bool(false)
bool(false)
bool(true) <- WHAT?
The function returns true for every string $needle, if the $haystack contains an element with the value 0!
Is it really by design? Or is it a bug and should be reported?

If you do not set the third parameter of in_array to true, comparison is done using type coercion.
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.
Under loose comparison rules, effectively 'a' is equal to 0 since (int)'a' == 0.

Related

Is this a bug in PHP arrays? [duplicate]

I have found some odd behaviour while I was using the PHP function in_array(). I have an array like this:
$arr = [TRUE, "some string", "something else"];
Now if I want to check if "test" is in the array it is clearly not, but in_array() still returns TRUE, why is that?
$result = in_array("test", $arr);
var_dump($result); //Output: bool(true)
The same thing happens when using array_search():
$result = array_search("test", $arr);
var_dump($result); //Output: int(0)
I thought maybe that the value TRUE in the array was automatically causing the function to return TRUE for every result without checking the rest of the array, but I couldn't find any documentation that would suggest that very odd functionality.
This behaviour of the function in_array() and array_search() is not a bug, but instead well documented behaviour.
Both functions have a 3rd optional parameter called $strict which by default is FALSE:
bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
mixed array_search ( mixed $needle , array $haystack [, bool $strict = false ] )
Now what that means is that by default both functions use loosely(==) comparison to compare the values. So they only check if the values are the same after PHP type juggling and without checking the type. Because of that in your example TRUE == "any none emtpy string" evaluates to TRUE.
So by setting the 3rd parameter to TRUE while calling the function you say that PHP should use strict(===) comparison and it should check value AND type of the values while comparing.
See this as a reference: How do the PHP equality (== double equals) and identity (=== triple equals) comparison operators differ?
You are right, the boolean can indeed cause this. Set the strict flag in the in_array function, this way also the type of the element is checked (basically the same as using ===):
if (in_array("username", $results, true)) // do something
if (in_array("password", $results, true)) // do something
if (in_array("birthday", $results, true)) // do something

Why in_array function return TRUE when we are looking for an empty string? [duplicate]

This question already has answers here:
PHP in_array() / array_search() odd behaviour
(2 answers)
Closed 6 years ago.
Could someone explain to me why that is true?
in_array('', array(0,1,2));
Because, as said in the docs:
bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
Searches haystack for needle using loose comparison unless strict is set.
... and '' == 0 is true in PHP. If you want to use strict comparison, just call in_array() with three params:
in_array('', array(0, 1, 2), true); // false
... so the types will be checked as well, and String '' won't have a chance to match against Numbers.
in_array by default performs loose comparison. Thus '' is equivalent to 0.
There is third argument (boolean) to in_array function which says if the matching is to be performed in STRICT way or not.
if you do in_array('', array(0,1,2), TRUE); then the result will be false.
Refer the documentation

in_array() always returns TRUE [duplicate]

This question already has answers here:
PHP in_array() / array_search() odd behaviour
(2 answers)
Closed 6 years ago.
$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?
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
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.

in_array() does not work [duplicate]

This question already has answers here:
PHP in_array() / array_search() odd behaviour
(2 answers)
Closed 6 years ago.
Why does this return true.
$needle = TRUE;
$haystack = array('that', 'this');
print in_array($needle, $haystack); // 1
EDIT: I am aware that one can pass in_array() the strict parameter to check types. I want to know why specifically the behaviour I show is exhibited.
Any non-empty string in PHP is equal to TRUE when loose comparison is made (i.e. type is ignored). You may test this by doing:
var_dump('this' == TRUE);
var_dump('that' == TRUE);
DEMO
But the results are quite different when strict comparison is made (i.e. type is taken into consideration):
var_dump('this' === TRUE);
var_dump('that' === TRUE);
DEMO
In order to enforce strict comparison in the function in_array, you have to set the optional third parameter to TRUE:
$needle = TRUE;
$haystack = array('that', 'this');
var_dump(in_array($needle, $haystack, TRUE));
DEMO

PHP Two Exclaimation Mark "!!" Operator with preg_match? [duplicate]

This question already has answers here:
Double not (!!) operator in PHP
(6 answers)
Closed 9 years ago.
Saw this online in one PHP snippet here.
/**
* #param string $str subject of test for integerness
* #return bool true if argument is an integer string
*/
function intStr($str) {
return !!preg_match('/^\d+$/', $str);
}
Running this code snippet produces:
> var_dump( intStr("abc") );
bool(false)
> var_dump( intStr("123") );
bool(true)
Questions:
Is the dual exclamation mark a a valid operator, or is it just the same as a "not-not", which negates itself?
Also, why is this operator used in-conjunction with the preg_match function?
preg_match returns 0 or 1 (or false on error) and this intStr function is meant to return a boolean value. A single !$x first converts $x to boolean, then negates. !!$x just reverts this negation, so it is a shorter way to write (bool)$x.
However, this saving of four characters results in loss of readability (and two unneccessary operations, but that's negligible), so it's not recommended.
It's clever code, but there is a rule in programming: Don't be clever
!! is equal to not not. That means that !!'a' will cast the string 'a' to a boolean, and return the inverse of that. So, !!preg_match means not not preg_match, so a valid preg_match.
Running this simplified function:
function test($value) {
return !!$value;
}
Tests:
> var_dump( test(1) );
bool(true)
> var_dump( test(0) );
bool(false)
> var_dump( test('1') );
bool(true)
> var_dump( test('0') );
bool(false)
> var_dump( is_bool( test('abc') ) );
bool(true)
> var_dump( is_bool( test('0') ) );
bool(true)
Observations:
Checked output using is_bool. Apparently it somehow casts/forces the output to a boolean.
Conclusion:
From the PHP manual,
preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or FALSE if an error occurred.
I can conclude that this function forces the return value to be a boolean value, instead of the possibility of an integer value returned by preg_match.

Categories