PHP has two ways to ask “are these the same?”.
==(equal) converts types if needed, then compares.===(identical) compares the value and the type, with no conversion.
<?php
var_dump(1 == "1");
var_dump(1 === "1");
var_dump(1 == 1.0);
var_dump(1 === 1.0);
bool(true)
bool(false)
bool(true)
bool(false)
1 and "1" are equal in value but not in type, so only == accepts them.
Surprises with ==
Loose comparison can give results that look wrong.
<?php
var_dump("abc" == 0); // PHP 8: false (PHP 7: true!)
var_dump(null == false);
var_dump("0" == false);
var_dump("" == null);
var_dump([] == false);
var_dump("1e3" == "1000"); // both look like numbers
bool(false)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
In PHP 7, "abc" == 0 was true, which caused real security holes. PHP 8 fixed that case. The rule for PHP 8: if both sides are numbers or numeric strings, compare as numbers. Otherwise, compare as strings. But the other surprises above still exist.
The same with ===
<?php
var_dump(null === false);
var_dump("0" === false);
var_dump("" === null);
var_dump([] === false);
var_dump("1e3" === "1000");
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
With ===, every one of those is false, which is what most people expect.
A real bug that === prevents
<?php
// strpos returns 0 when the text is at the very start
$position = strpos("PHP rocks", "PHP");
if ($position == false) {
echo "Not found (WRONG)\n";
}
if ($position === false) {
echo "Not found\n";
} else {
echo "Found at $position";
}
Not found (WRONG)
Found at 0
strpos() returns 0 for a match at the start, and 0 == false is true. Only === false tells the two cases apart. This is one of the most common PHP bugs.
Objects
For objects, == compares properties (same class, same values) and === checks that both variables point to the same object.
<?php
$a = new stdClass();
$b = new stdClass();
$c = $a;
var_dump($a == $b);
var_dump($a === $b);
var_dump($a === $c);
bool(true)
bool(false)
bool(true)
Make === your default
=== unless you can explain why you need ==. It removes a whole class of hidden bugs.