Comparison Operators
Comparison operators answer a yes-or-no question about two values and always return a boolean. PHP's comparison story has more nuance than most languages because of loose comparison, which converts types before comparing, versus strict comparison, which does not. Understanding the difference — and knowing when PHP's own rules changed between versions — will save you from some of the language's most infamous bugs.
Equality: == vs ===
== (loose equality) converts both operands to a common type before comparing their values. === (strict equality) compares both the value and the type, with no conversion at all. They are two different questions: "do these represent the same value?" versus "are these exactly the same value and type?"
Loose vs strict equality
<?php var_dump(1 == "1"); // bool(true) - "1" converts to 1 var_dump(1 === "1"); // bool(false) - int vs string var_dump(0 == false); // bool(true) - false converts to 0 var_dump(0 === false); // bool(false) - int vs bool var_dump(null == false); // bool(true) - both "empty-ish"
bool(true) bool(false) bool(true) bool(false) bool(true)
Inequality: != and <> vs !==
!= and its older alias <> are the loose-comparison negation of ==; !== is the strict-comparison negation of ===. As with equality, prefer the strict form whenever you can, since it removes an entire category of "why is this true" surprises.
Inequality operators
<?php
var_dump("5" != 5); // bool(false) - loose, both numeric
var_dump("5" !== 5); // bool(true) - strict, string vs intbool(false) bool(true)
Ordering operators
The familiar <, >, <=, and >= compare order — numerically for numbers, alphabetically (byte by byte) for plain strings. When comparing a number to a numeric string, PHP compares them numerically; comparing genuinely non-numeric strings falls back to string comparison rules.
Ordering examples
<?php
var_dump(5 > 3); // bool(true)
var_dump("apple" < "banana"); // bool(true) - alphabetical
var_dump("10" > "9"); // bool(true) - both numeric strings, compared as numbersThe PHP 8 loose comparison change
This is the single most important comparison detail to know if you learned PHP from older material. Before PHP 8, comparing a number to a non-numeric string first converted the number to a string, which produced surprising results like 0 == "abc" being true (because "abc" used to convert to 0). PHP 8 changed the rule: a number is now compared to a non-numeric string by converting the number to a string instead, so 0 == "abc" is false. Numeric strings like "123" still compare numerically as before.
0 == 'abc' before and after PHP 8
<?php
// On PHP 8+:
var_dump(0 == "abc"); // bool(false) - changed from PHP 7's bool(true)
var_dump(0 == ""); // bool(false) - changed as well
var_dump("1" == "01"); // bool(true) - both numeric strings, compare as numbers
var_dump("10" == "1e1"); // bool(true) - both numeric, 1e1 = 10
var_dump(100 == "1e2"); // bool(true) - 1e2 = 100bool(false) bool(false) bool(true) bool(true) bool(true)
The spaceship operator: <=>
The spaceship operator compares two values and returns an integer: -1 if the left side is smaller, 0 if they are equal, and 1 if the left side is larger. It exists mainly to make writing custom sort comparators trivial — the dedicated Null Coalescing & Spaceship page covers that use case in detail.
Spaceship operator
<?php var_dump(1 <=> 2); // int(-1) var_dump(2 <=> 2); // int(0) var_dump(3 <=> 2); // int(1)
int(-1) int(0) int(1)
Comparing arrays
== on two arrays checks that they have the same key/value pairs, regardless of the order the keys appear in. === additionally requires the same order and the same types for every value.
Array comparison
<?php $a = ["x" => 1, "y" => 2]; $b = ["y" => 2, "x" => 1]; var_dump($a == $b); // bool(true) - same pairs, order ignored var_dump($a === $b); // bool(false) - different key order
bool(true) bool(false)
Operator | Meaning | Type-checked? |
|---|---|---|
| Equal (value only) | No |
| Identical (value and type) | Yes |
| Not equal (value only) | No |
| Not identical | Yes |
| Ordering | No |
| Three-way comparison (-1, 0, 1) | No |
===and!==never convert types — the safest default for most conditionals.==and!=convert types, which is convenient but can hide bugs.PHP 8 fixed the classic
0 == "abc"surprise: it is nowfalse.<=>returns -1, 0, or 1 and is built for sorting callbacks.