Skip to content
Theory · Operators and comparison · lesson 4 of 8

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
<?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:

  1. 5 == '5' gives true: == turns the string '5' into a number and compares two fives.
  2. 5 === '5' gives false: there is an int on the left and a string on the right, and === stops checking right there.
  3. 5 === 5 gives true: 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.0 gives false: int and float are different types;
  • 5 == 5.0 gives true: after the conversion it is the same number;
  • !== answers the opposite question: 5 !== '5' gives true.

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:

  1. A number and a numeric string compare as numbers: 1 == '01' gives true.
  2. A number and a non-numeric string compare as strings: 0 == 'a' turns into '0' == 'a' and gives false.
  3. Two numeric strings compare as numbers too, although both are written in quotes.

Let's see these rules in code:

PHP
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 compares 1 with 1;
  • '10' < '9' gives false: as numbers, 10 is not less than 9, although alphabetically '1' comes before '9';
  • 'abc' < 'b': non-numeric strings compare letter by letter, like words in a dictionary;
  • null == false gives true: when compared with a bool, the value null turns into false.

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:

  • -1 if the left one is smaller: 1 <=> 2;
  • 0 if they are equal: 2 <=> 2;
  • 1 if 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 ==:

PHP
$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, 0 or 1.