Question

PHP Equality vs Identity: Understanding == and ===

phpoperators

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
  • null to 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 0 and false as the same thing
  • confusing an empty string with null
  • misreading user input from forms or APIs
  • incorrectly checking function results like strpos() or array_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
Take Quiz

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?

  • $a is an integer: 5
  • $b is a string: "5"
  • With ==, PHP converts types and compares the values.
  • With ===, PHP checks both type and value, so int is not the same as string.

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:

  • 0 if the match is found at the first position
  • false if 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

  • $a is an integer: 0
  • $b is a boolean: false

2. PHP performs type juggling

For loose comparison, PHP converts values to make them comparable.

3. Comparison result

  • 0 and false are treated as equal in loose comparison.
var_dump($a == $b); // true

Step-by-step for ===

1. PHP checks the type first

  • 0 is int
  • false is bool

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 == 42 becomes true.
  • "42" === 42
    • string is not int.
    • Result is false.

Rule of thumb

When stepping through comparisons:

  1. Ask: Are the types the same?
  2. If using ===, different types means false immediately.
  3. 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.

Take Quiz

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:

  1. normalize data first
  2. 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() returns 0 when the match is at the first character.
  • 0 == false is true.

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:

  • $_POST values 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 ===

OperatorNameCompares valueCompares typeType conversionCommon use
==EqualityYesNoYesRare, when loose matching is intentional
===IdentityYesYesNoDefault choice in most PHP code

Example outcomes

ExpressionResultWhy
5 == "5"trueString is converted to number
5 === "5"falseint and string differ
false == 0trueLoose conversion treats them as equal
false === 0falsebool and int differ
null == falsetrueLoose comparison can treat them similarly
null === falsefalseDifferent types

Related operators

OperatorMeaning
!=Loose not-equal
!==Strict not-identical

When to choose which

SituationBetter choiceReason
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
Take Quiz

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.

Take Quiz

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

  1. Create at least four pairs of values with different types, such as 5 and "5", 0 and false, null and false, and two arrays.
  2. For each pair, print the value types and the results of both == and ===.
  3. Include one example using strpos() or array_search() to show why === false is important.
  4. Add one example where you cast a string input to an integer before using ===.
Take Quiz

Keep learning

Related questions

View more