Comparing Objects

Ma Mahalakshmi V Updated 14 Nov 2026
5 min read ·Lesson 172 of 256

How PHP Compares Objects

In simple terms: "Are these two objects the same?" can mean two different things. Are they the same object (one thing referred to twice)? Or are they equal — two separate objects with the same contents, like two ₹500 notes? PHP has a separate operator for each question.

Technically:

OperatorNameTrue When
===IdentityBoth operands refer to the same instance
==EqualityBoth are instances of the same class and all properties are equal (compared with ==)
!== / !=NegationsThe opposite of the above

Identity vs Equality

<?php
final class Money
{
    public function __construct(private int $paise, private string $currency) {}
}

$a = new Money(50000, 'INR');
$b = new Money(50000, 'INR');
$c = $a;
$d = new Money(50000, 'USD');

var_dump($a == $b);    // equal contents
var_dump($a === $b);   // different instances
var_dump($a === $c);   // same instance
var_dump($a == $d);    // different currency

Output

bool(true)
bool(false)
bool(true)
bool(false)

How It Works

  1. $a and $b are separate objects with identical property values: equal (==) but not identical (===).
  2. $c = $a copies the object handle, so $a and $c are the same instance: identical.
  3. $a and $d differ in one property, so they are not equal.
  4. == compares all properties, including private ones.

Different Classes Are Never Equal

<?php
class Point
{
    public function __construct(public int $x, public int $y) {}
}

class Vector
{
    public function __construct(public int $x, public int $y) {}
}

var_dump(new Point(1, 2) == new Point(1, 2));
var_dump(new Point(1, 2) == new Vector(1, 2));

Output

bool(true)
bool(false)

Even with identical properties, objects of different classes are not equal with ==.


Object IDs

Every object alive at a given moment has a unique integer ID:

<?php
$first = new stdClass();
$second = $first;
$third = new stdClass();

var_dump(spl_object_id($first) === spl_object_id($second));
var_dump(spl_object_id($first) === spl_object_id($third));

Output

bool(true)
bool(false)

spl_object_id() (and the string version spl_object_hash()) identify instances — useful as array keys when tracking objects. IDs can be reused after an object is destroyed, so they are only unique among objects that exist at the same time. SplObjectStorage and WeakMap provide ready-made object-keyed collections.


The Limits of ==

== is convenient but often not what a domain means by "equal":

ProblemExample
Loose comparison of propertiesUntyped properties '500' and 500 count as equal
All properties countTwo User objects with the same ID but different "last login" are not equal
Business rules are ignoredEmail addresses differing only in letter case are not equal
Deep or circular structuresComparison recurses through nested objects; circular references cause a fatal "Nesting level too deep" error

A Dedicated equals() Method

For value objects, define equality explicitly:

<?php
final class EmailAddress
{
    private string $value;

    public function __construct(string $email)
    {
        $this->value = trim($email);
    }

    public function equals(EmailAddress $other): bool
    {
        return strtolower($this->value) === strtolower($other->value);
    }
}

$one = new EmailAddress('Asha@Example.com');
$two = new EmailAddress('asha@example.com');

var_dump($one == $two);
var_dump($one->equals($two));

Output

bool(false)
bool(true)

== compares the stored strings exactly, but for email addresses the case does not matter. equals() encodes the real rule, documents it, and uses strict comparisons internally.

Entities vs Value Objects

KindEqual WhenExample
Value objectAll relevant values are equalMoney(500, 'INR'), EmailAddress, DateRange
EntityThe identity (usually an ID) is the sameCustomer #7 remains the same customer after changing the address
public function sameAs(Customer $other): bool
{
    return $this->id === $other->id;
}

Comparing Dates

DateTimeImmutable and DateTime objects are an exception: comparison operators compare the moment in time, regardless of time zone:

<?php
$india = new DateTimeImmutable('2026-10-15 10:00', new DateTimeZone('Asia/Kolkata'));
$utc = new DateTimeImmutable('2026-10-15 04:30', new DateTimeZone('UTC'));
$later = new DateTimeImmutable('2026-10-15 11:00', new DateTimeZone('Asia/Kolkata'));

var_dump($india == $utc);
var_dump($india < $later);

Output

bool(true)
bool(true)

10:00 in India and 04:30 UTC are the same moment, so the objects are equal even though their time zones differ. For other classes, avoid < and >: PHP compares objects property by property, which rarely has a meaningful result. Implement methods such as isGreaterThan() instead.


Searching Arrays of Objects

in_array() compares loosely by default, which uses == for objects:

<?php
final class Money
{
    public function __construct(public readonly int $paise) {}

    public function equals(Money $other): bool
    {
        return $this->paise === $other->paise;
    }
}

$payments = [new Money(10000), new Money(25000)];
$target = new Money(25000);

var_dump(in_array($target, $payments));          // loose: equal contents
var_dump(in_array($target, $payments, true));    // strict: same instance?
var_dump(array_any($payments, fn(Money $m): bool => $m->equals($target)));   // PHP 8.4+

Output

bool(true)
bool(false)
bool(true)
  • Loose in_array() finds an equal object.
  • Strict in_array() looks for the same instance, which $target is not.
  • array_any() with equals() expresses the intended rule explicitly (in older PHP versions, use a loop or array_filter()).

Practical Example: Merging Duplicate Cart Lines

<?php
final class CartLine
{
    public function __construct(
        public readonly string $sku,
        public readonly string $size,
        public int $quantity,
    ) {}

    public function isSameProductAs(CartLine $other): bool
    {
        return $this->sku === $other->sku && $this->size === $other->size;
    }
}

function addToCart(array $lines, CartLine $new): array
{
    foreach ($lines as $line) {
        if ($line->isSameProductAs($new)) {
            $line->quantity += $new->quantity;
            return $lines;
        }
    }

    $lines[] = $new;
    return $lines;
}

$cart = [];
$cart = addToCart($cart, new CartLine('TSHIRT-01', 'M', 1));
$cart = addToCart($cart, new CartLine('TSHIRT-01', 'L', 1));
$cart = addToCart($cart, new CartLine('TSHIRT-01', 'M', 2));

foreach ($cart as $line) {
    echo "{$line->sku} ({$line->size}) × {$line->quantity}\n";
}

Output

TSHIRT-01 (M) × 3
TSHIRT-01 (L) × 1

== would treat the first and third lines as different (their quantities differ), and === would never match a newly created line. The domain rule — "same SKU and same size" — is expressed in isSameProductAs().


Common Mistakes

Using === to Compare Values

Effect: Two equal value objects are reported as different.

Fix: Use == for simple cases, or better, an equals() method.

Using == for Domain Equality

Effect: Irrelevant properties (timestamps, caches) make equal things unequal, or loose comparison makes different things equal.

Fix: Implement explicit equality methods.

Comparing Objects With < and >

Effect: Meaningless results for most classes.

Fix: Write comparison methods (or a comparator for usort()).

Comparing Objects With Circular References Using ==

Effect: Fatal "Nesting level too deep" error.

Fix: Compare identities or IDs.


Best Practices

  • Use === to check whether two variables refer to the same instance.
  • Give value objects an equals() method encoding the real equality rule.
  • Compare entities by identifier.
  • Use strict searching or callbacks with explicit comparison methods for arrays of objects.
  • Rely on built-in comparison operators only for types that define them meaningfully, such as dates.

Official reference: https://www.php.net/manual/en/language.oop5.object-comparison.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Tutorial Index PHP Home PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope Static Variables Variable Variables PHP Echo / Print PHP printf / sprintf PHP Data Types PHP Booleans PHP NULL PHP Strings String Functions Modify Strings Concatenate Strings Slicing Strings Escape Characters String Interpolation Heredoc and Nowdoc Search in Strings Multibyte Strings PHP Floats PHP Casting PHP Type Juggling PHP Math PHP Random Numbers PHP Constants PHP Magic Constants PHP Operators Arithmetic Operators Assignment Operators Comparison Operators Increment / Decrement Operators Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence PHP If...Else...Elseif PHP If PHP If Operators PHP If...Else PHP Shorthand if PHP Nested if PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement Continue Statement PHP Functions User-defined Functions Function Arguments Default Argument Values Pass by Reference Named Arguments Variadic Functions Return Values Type Declarations in Functions Recursive Functions Variable Functions Anonymous Functions Closures Arrow Functions First-class Callable Syntax PHP Arrays Indexed Arrays Associative Arrays Create Arrays Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays array_map / array_filter / array_reduce Array Functions PHP Superglobals $GLOBALS $_SERVER $_REQUEST $_POST $_GET $_FILES $_COOKIE $_SESSION \$\_ENV PHP RegEx RegEx Patterns RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions PHP Form Handling PHP Form Validation PHP Form Required PHP Form URL/E-mail Form Input Sanitizing Escaping Output (htmlspecialchars) Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting DateTime Class Timezones PHP Include Include vs Require PHP File Handling PHP File Open/Read PHP File Create/Write File Delete / Rename / Copy PHP Directories PHP CSV Files PHP File Upload PHP Cookies PHP Sessions PHP Filters PHP Filters Advanced PHP Callback Functions PHP JSON PHP Exceptions Error Handling Custom Error Handler Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators PHP What is OOP PHP Classes/Objects The $this Keyword PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Destructor PHP Access Modifiers Readonly Properties PHP Inheritance Method Overriding The final Keyword PHP Class Constants PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning Comparing Objects Anonymous Classes PHP Enums PHP Namespaces Autoloading Classes PHP Iterables Iterators Object Serialization Strict Types Union Types Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where MySQL Order By MySQL Delete Data MySQL Update Data MySQL Limit Data MySQL Joins with PHP Pagination with PHP PDO Introduction PDO Connect PDO Prepared Statements PDO Fetch Modes PDO Transactions PDO Error Handling PHP XML Parsers PHP SimpleXML Parser PHP SimpleXML - Get PHP XML Expat Parser PHP DOM Parser PHP XMLReader PHP XMLWriter AJAX Intro AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention CSRF Protection Session Security Secure Cookies File Upload Security Filesystem Security Error Reporting in Production Hiding PHP Encryption with Sodium PHP Configuration (php.ini) PHP Command Line (CLI) Composer PSR-4 Autoloading Installing Extensions (PECL / PIE) Debugging PHP OPcache & Performance Garbage Collection PHP-FPM Migrating to PHP 8 Project: Contact Form with Email Project: Login & Registration System Project: CRUD App with MySQL Project: Image Upload Gallery Project: Shopping Cart with Sessions Project: Simple Blog Project: REST API with PHP
Ask about this post
AI Ask about this post

Ask questions about Comparing Objects and get answers drawn from it.

Signed-in readers only.