Why does == behave strangely in PHP?
== converts operands to a common type before comparing, which produces results that look wrong. === compares type and value, and should be your default.
0 == "a" // false in PHP 8 (was true in PHP 7)
"1" == "01" // true — both converted to int 1
"10" == "1e1" // true — both are numeric strings
100 == "1e2" // true
null == false // true
[] == false // true
"abc" == 0 // false in PHP 8, true in PHP 7PHP 8 fixed the worst of these — comparing a number to a non-numeric string now converts the number to a string rather than the reverse. But numeric strings still compare loosely, and that is enough to cause real bugs.
#Just use ===
"1" === "01" // false
100 === "1e2" // false
null === false // false=== is true only when the type and the value both match. Same for !==.
#Where it actually bites
in_array('1', $ids); // loose by default
in_array('1', $ids, true); // strict — do this
array_search($needle, $hay, true);
array_keys($array, $value, true);These functions default to loose comparison. Always pass the strict flag.
#The switch statement is loose
switch uses == internally and cannot be made strict. When the cases are typed values, use match (PHP 8+), which is strict:
$label = match($status) {
1, 2 => 'active',
0 => 'inactive',
default => 'unknown',
};#And functions that return 0 or false
if (strpos($haystack, $needle) !== false) { }strpos returns 0 for a match at the start, which is falsy. !== false is the only correct check. The same applies to filter_var, which returns false on failure but can legitimately return 0.