Menu
Coddy logo textTech

Object Cloning Deep Dive

Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 61 of 91.

You learned about the __clone magic method earlier in this course. Now let's explore the critical difference between shallow and deep cloning when objects contain other objects as properties.

By default, PHP performs a shallow copy when cloning. Scalar values are duplicated, but object properties remain as references to the same objects:

<?php
class Address {
    public function __construct(public string $city) {}
}

class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;

$clone->name = "Bob";
$clone->address->city = "London";

echo $original->name . " - " . $original->address->city;

Output:

Alice - London

Notice that changing $clone->name didn't affect the original, but changing the address city did! Both objects share the same Address instance.

To create a deep copy where nested objects are also cloned, implement __clone:

<?php
class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
    
    public function __clone(): void {
        $this->address = clone $this->address;
    }
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;
$clone->address->city = "London";

echo $original->address->city;

Output:

Paris

Now each Person has its own independent Address. When your objects contain multiple nested objects, you must clone each one in __clone to achieve true independence between the original and the copy.

challenge icon

Challenge

Easy

Let's build a document management system that demonstrates the difference between shallow and deep cloning. You'll create documents that contain author information, and ensure that cloning a document creates a truly independent copy.

You'll organize your code across three files:

  • Author.php — Create an Author class that represents a document's author. Use constructor promotion to define a public $name (string) and a public $email (string).
  • Document.php — Create a Document class that contains an author. Include the Author file. The class should:
    • Use constructor promotion for a public $title (string) and a public $author (Author)
    • Implement the __clone() magic method to perform deep cloning — when a document is cloned, its author should also be cloned so changes to the clone's author don't affect the original
    • Have a method getInfo() that returns "[title] by [author name] ([author email])"
  • main.php — Include the Document file. You'll receive three inputs: a document title, an author name, and an author email.

    Create a Document with an Author using the provided inputs. Clone the document, then modify the clone's author name by appending " (Copy)" to it and change the clone's title by prepending "Copy of " to it.

    Print two lines:

    • The original document's info
    • The cloned document's info

    If your deep cloning is implemented correctly, the original document's author should remain unchanged even after modifying the clone's author.

This challenge demonstrates why deep cloning matters — without proper implementation of __clone(), both documents would share the same Author object, and changing one would affect the other.

Cheat sheet

By default, PHP performs a shallow copy when cloning objects. Scalar values are duplicated, but object properties remain as references to the same objects.

Example of shallow cloning:

<?php
class Address {
    public function __construct(public string $city) {}
}

class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;

$clone->name = "Bob";
$clone->address->city = "London";

echo $original->name . " - " . $original->address->city;
// Output: Alice - London

Changing $clone->name doesn't affect the original, but changing the nested address object does because both objects share the same Address instance.

To create a deep copy where nested objects are also cloned, implement the __clone magic method:

<?php
class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
    
    public function __clone(): void {
        $this->address = clone $this->address;
    }
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;
$clone->address->city = "London";

echo $original->address->city;
// Output: Paris

When objects contain multiple nested objects, you must clone each one in __clone to achieve true independence between the original and the copy.

Try it yourself

<?php

require_once 'Document.php';

// Read inputs
$title = trim(fgets(STDIN));
$authorName = trim(fgets(STDIN));
$authorEmail = trim(fgets(STDIN));

// TODO: Create an Author with the provided name and email

// TODO: Create a Document with the provided title and the Author

// TODO: Clone the document

// TODO: Modify the clone's author name by appending " (Copy)" to it

// TODO: Modify the clone's title by prepending "Copy of " to it

// TODO: Print the original document's info

// TODO: Print the cloned document's info

?>
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming