Comparison: == and ===
A program compares things all the time: whether a password matched, whether there is enough money, whether one number is bigger than another. The result of a comparison is a value of type bool, true or false, and you print it with var_dump.
Imagine a shop with two cashiers. The lenient one takes the string '5' for the number 5, as long as the total adds up. The strict one also checks the kind: a number is a number and a string is a string, even if it holds the same five.
In PHP the lenient cashier is called ==, and the strict one ===:
<?php
var_dump(5 == '5'); // bool(true)
var_dump(5 === '5'); // bool(false)
var_dump(5 === 5); // bool(true)Let's go through it line by line:
5 == '5'givestrue:==turns the string'5'into a number and compares two fives.5 === '5'givesfalse: there is aninton the left and astringon the right, and===stops checking right there.5 === 5givestrue: both the type and the value match.
Loose comparison ==
Loose comparison with == first brings both values to a common type and then compares them. Its partner != answers the opposite question: 5 != '5' gives false, because the values are equal after the conversion.
The operators <, >, <= and >= compare by the same loose rules: '10' > 9 gives true.
Strict comparison ===
Strict comparison with === converts nothing. It is true only when both the type and the value match:
5 === 5.0givesfalse:intandfloatare different types;5 == 5.0givestrue: after the conversion it is the same number;!==answers the opposite question:5 !== '5'givestrue.
The PHP 8 rule for numbers and strings
The trickiest part of == is comparing a number with a string. What matters here is whether the string is numeric. A numeric string spells out a number from start to end: '42', '01', '4.2', '1e3'.
Since PHP 8 the rules are these:
- A number and a numeric string compare as numbers:
1 == '01'givestrue. - A number and a non-numeric string compare as strings:
0 == 'a'turns into'0' == 'a'and givesfalse. - Two numeric strings compare as numbers too, although both are written in quotes.
Let's see these rules in code:
var_dump(0 == 'a'); // bool(false)
var_dump('1' == '01'); // bool(true)
var_dump('10' < '9'); // bool(false)
var_dump('abc' < 'b'); // bool(true)
var_dump(null == false); // bool(true)What happens here:
'1' == '01': both strings are numeric, and PHP compares1with1;'10' < '9'givesfalse: as numbers,10is not less than9, although alphabetically'1'comes before'9';'abc' < 'b': non-numeric strings compare letter by letter, like words in a dictionary;null == falsegivestrue: when compared with abool, the valuenullturns intofalse.
Before PHP 8 the expression 0 == 'a' was true: PHP turned a string without digits into 0. Interviewers like to ask this: "What changed in comparing a number with a string in PHP 8?" The answer:
- a number and a non-numeric string now compare as strings, so
0 == 'a'is false; - two numeric strings still compare as numbers, so
'1' == '01'is true; - PHP 8 did not make
==strict: only===gives a strict comparison.
The cashier picture needs a caveat here. The leniency of == is not goodwill but a fixed rulebook: a real cashier may change their mind, while == always does exactly what is written above.
Compare with === by default. Keep == for the cases where you deliberately treat 1 and '1' as one value.
The <=> operator
The <=> operator compares two values and answers with a number:
-1if the left one is smaller:1 <=> 2;0if they are equal:2 <=> 2;1if the left one is bigger:3 <=> 2.
It compares by the same loose rules, so '10' <=> '9' gives 1. Because of its shape it is called the "spaceship".
Common mistake
A PIN from a form is checked with ==:
$pin = '0123';
$ok = $pin == '123'; // ✗
var_dump($ok); // bool(true)Both strings are numeric, so == compares them as the numbers 123 and 123. The wrong PIN got through, and PHP said nothing. With === the strings are compared as they are: $pin === '123' gives bool(false).
Key points
==converts types before comparing, while===needs both the type and the value to match.- Since PHP 8 a number and a non-numeric string compare as strings:
0 == 'a'is false. ==compares two numeric strings as numbers:'1' == '01'is true, and'10' < '9'is false.- Compare with
===by default;<=>returns-1,0or1.