๐Ÿ“ Web Development

PHP Comparison Operators: ==, === and the Type Trap

Aug 26, 20265 min read11 viewsBy Flow

PHP comparison operators ask a question and answer true or false. There are ten, counting both spellings of "not equal", and you will use three of them constantly. The catch is that two of those three, == and ===, look almost identical and disagree far more often than beginners expect โ€” and PHP 8 changed the rules on one of them.

All ten PHP comparison operators

The full set, with what each one actually asks.

OperatorNameTrue when
==EqualValues match after PHP converts types
===IdenticalValue and type both match
!=Not equalValues differ after conversion
<>Not equalSame as !=, older spelling
!==Not identicalValue or type differs
<Less than
>Greater than
<=Less than or equal
>=Greater than or equal
<=>SpaceshipReturns -1, 0 or 1 โ€” not a boolean

Use != rather than <>. They do the same thing, but nobody writes <> in new code.

Loose == against strict ===

This is the pair that matters.

<?php
$number = 10;
$text   = "10";

var_dump($number == $text);
var_dump($number === $text);
?>

Output

PHP comparison operators output showing loose equals true and strict equals false for 10 and the string 10

== says they are equal. === says they are not.

$number holds the integer 10. $text holds the two characters "10". They look alike on screen and they are not the same thing in memory.

== converts one side before comparing. === refuses to convert and checks the type as well.

This matters because everything arriving from outside your program is text. Form fields, URL parameters, JSON, most database drivers โ€” all strings, even when the value looks like a number. That is where the guessing starts.

What PHP 8 changed about ==

Most tutorials on the web still describe PHP 7 behaviour here, so this section is worth reading even if you think you know ==.

<?php
var_dump(0 == "flow");
var_dump(0 == "");
var_dump("1" == "01");
var_dump(100 == "1e2");
?>

Output

PHP comparison operators output on PHP 8 where zero no longer equals a non numeric string

On PHP 8 the first two are false and the last two are true.

On PHP 7 the first two were true, and that caused real security bugs. PHP used to convert the string to a number, and a word with no digits in it became 0. So 0 == "flow" was true, and any code comparing a numeric ID against user text could be tricked.

PHP 8 flipped the rule. When a number meets a non-numeric string, PHP now turns the number into a string and compares them as text. "0" and "flow" are plainly different, so the answer is false.

Two numeric strings still compare as numbers, which is why "1" == "01" and 100 == "1e2" are both true. Scientific notation counts as numeric.

None of this affects ===. It never converted anything, so it never needed fixing.

!= and !==

The negatives follow the same split.

<?php
$number = 10;
$text   = "10";

var_dump($number != $text);
var_dump($number !== $text);
?>

Output

PHP comparison operators output showing not equal false and not identical true for the same two values

!= is false โ€” after conversion the values match, so they are not "not equal". !== is true, because the types differ.

The rule is the same as before: three characters means strict, two means loose.

The spaceship operator

<=> is the odd one out. It does not return true or false โ€” it returns a number.

<?php
var_dump(1 <=> 2);
var_dump(2 <=> 2);
var_dump(3 <=> 2);
?>

Output

PHP comparison operators spaceship output returning minus one, zero and one

Left smaller gives -1. Equal gives 0. Left bigger gives 1.

That is precisely what PHP's sorting functions want back from you, which is the whole reason the operator exists.

<?php
$marks = [82, 91, 68];

usort($marks, function ($a, $b) {
    return $b <=> $a;
});

print_r($marks);
?>

Output

PHP comparison operators used in usort, sorting marks 91, 82 and 68 highest first

Highest first. Swap $b <=> $a to $a <=> $b and you get lowest first. Before PHP 7 you had to write three lines of if statements to say the same thing.

Comparing arrays

PHP comparison operators work on arrays too, and the loose-versus-strict split changes meaning here.

<?php
$a = ["x" => 1, "y" => 2];
$b = ["y" => 2, "x" => 1];

var_dump($a == $b);
var_dump($a === $b);
?>

Output

PHP comparison operators on arrays showing loose equals true and strict equals false when the key order differs

== is true: both arrays hold the same keys with the same values. === is false: it also demands the same order and the same types.

So for arrays, == asks "same contents?" and === asks "same contents, same order?". Neither is wrong โ€” pick the question you actually mean.

Which should you use?

Reach for === and !== by default. You will never be surprised by a conversion you did not ask for.

Use == deliberately, when you genuinely want "10" and 10 to count as the same โ€” comparing a form field against a number you already trust, for instance. Even then, converting the input yourself with (int) first is clearer than leaning on PHP to guess.

And never test a form field with if ($value == true). Use isset() and !== '' to say what you mean.

Common questions about PHP comparison operators

The comparison questions people search for most.

What is the difference between == and === in PHP?

== compares values after converting types, so 10 == "10" is true. === compares value and type, so 10 === "10" is false. Use === by default, because form and database data arrives as text.

Is 0 == "abc" true in PHP?

Not any more. On PHP 8 it is false. On PHP 7 it was true, because PHP converted the string to the number 0. The rule changed in PHP 8 to compare them as strings instead.

What is the <=> operator in PHP?

The spaceship operator. It returns -1, 0 or 1 depending on whether the left side is smaller than, equal to or larger than the right. It is built for sort callbacks like usort().

What is the difference between = and == in PHP?

One equals sign assigns. Two compare. if ($status = "active") does not test anything โ€” it overwrites $status and is always true. That is a single missing character and it is the most common PHP typo there is.

Can you compare two arrays with PHP comparison operators?

Yes. == is true when both arrays hold the same key and value pairs, in any order. === also requires the same order and the same types.

What is next

You can now compare anything in PHP without PHP quietly changing it behind your back.

The reason !$age > 10 does not do what it looks like is precedence โ€” read PHP operator precedence: what runs first and why. For the full set of operators from scratch, go back to PHP operators: arithmetic, comparison and logical.

Comments

Loading comments...

Link copied to clipboard