Question
In PHP, what is the difference between the == equality operator and the === identity operator?
How does loose comparison with == work, and how does strict comparison with === work?
Please include practical examples that show when the results are different.
$a = 5;
$b = "5";
var_dump($a == $b); // ?
var_dump($a === $b); // ?
Short Answer
By the end of this page, you will understand how PHP compares values using == and ===, why type coercion matters, and why === is usually safer in real code. You will also see examples involving numbers, strings, booleans, null, and arrays so you can predict comparison results more confidently.
Concept
In PHP, == and === both compare two values, but they do not behave the same way.
==checks whether two values are equal after PHP converts types if needed.===checks whether two values are identical, meaning both the value and the type must already match.
This difference matters because PHP is a loosely typed language. A variable can hold different types of values, and PHP may automatically convert one type to another during some operations. That automatic conversion is called type juggling.
Loose comparison: ==
When you use ==, PHP tries to make the two operands comparable. That can involve converting:
- strings to numbers
- booleans to integers
nullto other empty-like values in some cases
This can produce results that look surprising at first.
var_dump(5 == "5"); // true
var_dump(false == 0); // true
var_dump(null == false); // true
The values are considered equal because PHP converts types before comparing.
Strict comparison: ===
When you use ===, PHP does no type conversion for equality checking. The values must already be the same type and the same value.
var_dump(5 === "5"); // false
var_dump(false === 0); // false
var_dump(null === false); // false
This is usually easier to reason about because the result is more predictable.
Why this matters in real programming
Using the wrong comparison operator can cause bugs such as:
- treating
0andfalseas the same thing - confusing an empty string with
null - misreading user input from forms or APIs
- incorrectly checking function results like
strpos()orarray_search()
In most modern PHP code, developers prefer === unless they specifically need loose comparison behavior.
Mental Model
Think of == as saying:
"These two things look the same after I normalize them."
Think of === as saying:
"These two things are exactly the same item type and value."
A simple analogy:
==is like comparing two addresses after removing spaces, punctuation, and formatting differences.===is like checking whether the addresses are character-for-character identical.
Another analogy with boxes:
- Every value is stored in a box with a label (its type) and contents (its value).
==mostly compares the contents, even if the labels differ.===compares both the label and the contents.
So for PHP:
5 == "5" // same content after conversion
5 === "5" // different labels: int vs string
Syntax and Examples
Core syntax
$value1 == $value2 // loose comparison
$value1 === $value2 // strict comparison
Basic example
$a = 5;
$b = "5";
var_dump($a == $b); // true
var_dump($a === $b); // false
Why?
$ais an integer:5$bis a string:"5"- With
==, PHP converts types and compares the values. - With
===, PHP checks both type and value, sointis not the same asstring.
More examples
Numbers and strings
var_dump(10 == "10"); // true
var_dump(10 === "10"); // false
Booleans and integers
var_dump(false == 0); // true
var_dump(false === 0); // false
var_dump(true == 1); // true
var_dump(true === 1); // false
Null and false
var_dump(null == false); // true
var_dump(null === false); // false
Strings
var_dump("hello" == "hello"); // true
var_dump("hello" === "hello"); // true
Arrays
For arrays, == checks whether key/value pairs are equal, even if types of values can be loosely equal. === also requires the same order and the same types.
$a = ["1", 2];
$b = [1, 2];
var_dump($a == $b); // true
var_dump($a === $b); // false
$x = ["a" => 1, "b" => 2];
$y = ["b" => 2, "a" => 1];
var_dump($x == $y); // true
var_dump($x === $y); // false
A very important real-world example
$pos = strpos("hello", "h");
var_dump($pos); // int(0)
var_dump($pos == false); // true <- dangerous
var_dump($pos === false); // false <- correct
strpos() returns:
0if the match is found at the first positionfalseif no match is found
If you use == false, PHP treats 0 as equal to false, which can create a bug. This is one of the most common reasons to prefer ===.
Step by Step Execution
Consider this example:
$a = 0;
$b = false;
var_dump($a == $b);
var_dump($a === $b);
Step-by-step for ==
1. PHP sees different types
$ais an integer:0$bis a boolean:false
2. PHP performs type juggling
For loose comparison, PHP converts values to make them comparable.
3. Comparison result
0andfalseare treated as equal in loose comparison.
var_dump($a == $b); // true
Step-by-step for ===
1. PHP checks the type first
0isintfalseisbool
2. Types do not match
Because the types are different, PHP immediately returns false.
var_dump($a === $b); // false
Another trace example
$x = "42";
$y = 42;
var_dump($x == $y); // true
var_dump($x === $y); // false
Execution
"42" == 42- PHP converts the string to a number.
42 == 42becomestrue.
"42" === 42stringis notint.- Result is
false.
Rule of thumb
When stepping through comparisons:
- Ask: Are the types the same?
- If using
===, different types meansfalseimmediately. - If using
==, ask: How might PHP convert one value before comparing?
Real World Use Cases
1. Validating form input
Form values usually arrive as strings.
$age = $_POST['age']; // "18"
if ($age == 18) {
echo "Loose match";
}
if ($age === 18) {
echo "Strict match";
}
Here, the first condition is true, but the second is false because form input is a string unless you convert it.
2. Checking function return values
Some PHP functions return either a normal value or false.
$index = array_search("apple", ["apple", "banana"]);
if ($index === false) {
echo "Not found";
} else {
echo "Found at index $index";
}
This is safer than == false because index 0 is a valid result.
3. API and JSON data
JSON often turns values into strings, numbers, booleans, or null depending on the source.
$data = json_decode('{"active": true, "count": 5}', true);
var_dump($data['active'] === true); // true
var_dump($data['count'] === 5); // true
Strict checks help ensure the data shape is exactly what your code expects.
4. Configuration values
Environment variables are typically strings.
$debug = getenv('APP_DEBUG'); // might be "0" or "1"
if ($debug == true) {
echo "Debug may appear enabled unexpectedly";
}
It is safer to explicitly convert values first and then use strict comparison.
5. Optional values and null checks
$username = $data['username'] ?? null;
if ($username === null) {
echo "No username provided";
}
This clearly checks for missing data without mixing null, false, and empty strings.
Real Codebase Usage
In real PHP projects, developers usually follow one simple rule:
- Use
===and!==by default. - Use
==only when you intentionally want type juggling.
Common patterns
Guard clauses
if ($user === null) {
return;
}
This makes it clear that only null should trigger the early return.
Validation
if (!is_int($age)) {
throw new InvalidArgumentException('Age must be an integer.');
}
After validating types, strict comparisons become reliable.
Function result checks
$pos = strpos($text, $needle);
if ($pos === false) {
// not found
}
This avoids confusing 0 with false.
Explicit conversion before comparison
$age = (int) $_POST['age'];
if ($age === 18) {
echo 'Adult threshold reached';
}
This is better than relying on == because the conversion is visible and intentional.
Filtering and data normalization
$ids = array_map('intval', $_POST['ids']);
foreach ($ids as $id) {
if ($id === 0) {
continue;
}
}
A common pattern is:
- normalize data first
- compare strictly afterward
Team conventions
Many teams and coding standards prefer strict comparison because:
- it reduces hidden behavior
- it prevents edge-case bugs
- it makes code reviews easier
- it improves readability and intent
Common Mistakes
1. Using == false with functions that can return 0
Broken code:
$pos = strpos("hello", "h");
if ($pos == false) {
echo "Not found";
}
Why it is wrong:
strpos()returns0when the match is at the first character.0 == falseistrue.
Correct code:
if ($pos === false) {
echo "Not found";
}
2. Assuming form input numbers are actual integers
Broken code:
$quantity = $_POST['quantity']; // "3"
if ($quantity === 3) {
echo "Three items";
}
Why it fails:
$_POSTvalues are usually strings.
Fix it by converting first:
$quantity = (int) $_POST['quantity'];
if ($quantity === 3) {
echo "Three items";
}
3. Treating empty values as the same thing
Broken assumption:
var_dump("" == 0);
var_dump(false == "0");
Loose comparisons between empty-like values can be confusing. Avoid relying on them unless you fully understand the conversion rules.
4. Comparing booleans to strings loosely
var_dump(true == "1"); // true
var_dump(false == ""); // true in loose contexts can surprise people
If you mean boolean logic, convert to booleans explicitly or compare strictly.
5. Using === without normalizing data
=== is safer, but it can still fail if your data comes in the wrong type.
$id = $_GET['id']; // "25"
var_dump($id === 25); // false
Fix:
$id = (int) $_GET['id'];
var_dump($id === 25); // true
How to avoid most mistakes
- Prefer
===and!== - Convert input to the expected type first
- Be careful with
0,false,null, and empty strings - Read the return types of built-in functions
Comparisons
== vs ===
| Operator | Name | Compares value | Compares type | Type conversion | Common use |
|---|---|---|---|---|---|
== | Equality | Yes | No | Yes | Rare, when loose matching is intentional |
=== | Identity | Yes | Yes | No | Default choice in most PHP code |
Example outcomes
| Expression | Result | Why |
|---|---|---|
5 == "5" | true | String is converted to number |
5 === "5" | false | int and string differ |
false == 0 | true | Loose conversion treats them as equal |
false === 0 | false | bool and int differ |
null == false | true | Loose comparison can treat them similarly |
null === false | false | Different types |
Related operators
| Operator | Meaning |
|---|---|
!= | Loose not-equal |
!== | Strict not-identical |
When to choose which
| Situation | Better choice | Reason |
|---|---|---|
Checking if a function returned false | === | Avoid confusing 0 or "" with false |
| Comparing user input after casting | === | Clear and predictable |
| Comparing already-normalized values | === | Stronger intent |
| Intentionally accepting equivalent values across types | == | Only when type coercion is desired |
Cheat Sheet
Quick rules
==means equal after possible type conversion===means same type and same value- Prefer
===in most code - Convert input first, then compare strictly
Syntax
$a == $b
$a === $b
$a != $b
$a !== $b
Common examples
5 == "5" // true
5 === "5" // false
false == 0 // true
false === 0 // false
null == false // true
null === false // false
Safe pattern
$age = (int) $_POST['age'];
if ($age === 18) {
echo 'OK';
}
Dangerous pattern
if (strpos($text, $needle) == false) {
// can be wrong when result is 0
}
Safe alternative
if (strpos($text, $needle) === false) {
// definitely not found
}
Remember
0,false,null,"", and"0"can be tricky in loose comparisons- If the type matters, use
=== - If the type does not matter, make sure loose comparison is truly intended
FAQ
What is the difference between == and === in PHP?
== compares values loosely and may convert types first. === compares both value and type without conversion.
Should I use == or === in PHP?
In most cases, use ===. It is safer, clearer, and avoids bugs caused by automatic type conversion.
Why does 5 == "5" return true in PHP?
Because == performs loose comparison. PHP converts the string "5" to the number 5, then compares them.
Why does 5 === "5" return false?
Because === requires both operands to have the same type and value. One is an integer and the other is a string.
Why is strpos() often checked with === false?
Because strpos() can return 0 for a valid match at the beginning of a string. Using == false would incorrectly treat 0 as false.
Does === make PHP strongly typed?
No. PHP is still a dynamically typed language. === simply performs a stricter comparison.
Can arrays be compared with == and ===?
Yes. With ==, arrays are equal if they contain the same key/value pairs. With ===, they must also have the same order and matching value types.
When is == useful in PHP?
It can be useful when you intentionally want equivalent values across types to match, but this is less common in modern PHP code.
Mini Project
Description
Build a small PHP script that checks values entered from different sources and shows the difference between loose and strict comparison. This project demonstrates how real input often arrives as strings and why strict comparison becomes more reliable after normalization.
Goal
Create a PHP script that compares several pairs of values using both == and === and prints the results clearly.
Requirements
- Create at least four pairs of values with different types, such as
5and"5",0andfalse,nullandfalse, and two arrays. - For each pair, print the value types and the results of both
==and===. - Include one example using
strpos()orarray_search()to show why=== falseis important. - Add one example where you cast a string input to an integer before using
===.
Keep learning
Related questions
Are PDO Prepared Statements Enough to Prevent SQL Injection in PHP?
Learn how PDO prepared statements prevent SQL injection in PHP, what they protect, and the mistakes that still leave MySQL apps vulnerable.
Can You Bind an Array to an IN Clause in PHP PDO?
Learn how PDO handles placeholders in IN() clauses, why arrays cannot be bound directly, and the safe PHP pattern to build dynamic queries.
Choosing the Right MySQL Collation for PHP and UTF-8
Learn how MySQL character sets and collations work with PHP, and how to choose a practical UTF-8 setup for web applications.