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.
| Operator | Name | True when |
|---|---|---|
== | Equal | Values match after PHP converts types |
=== | Identical | Value and type both match |
!= | Not equal | Values differ after conversion |
<> | Not equal | Same as !=, older spelling |
!== | Not identical | Value or type differs |
< | Less than | |
> | Greater than | |
<= | Less than or equal | |
>= | Greater than or equal | |
<=> | Spaceship | Returns -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

== 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

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

!= 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.



Loading comments...