Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP deep clone object

Tags:

object

clone

php

The scenario: fetch an email template from the database, and loop through a list of recipients, personalising the email for each.

My email template is returned as a nested object. It might look a little like this:

object(stdClass) {
    ["title"] => "Event Notification"
    ["sender"] => "[email protected]"
    ["content"] => object(stdClass) {
        ["salutation"] => "Dear %%firstname%%,"
        ["body"] => "Lorem ipsum %%recipient_email%% etc etc..."
    }
}

Then I loop through the recipients, passing this $email object to a personalise() function:

foreach( $recipients as $recipient ){
    $email_body = personalise( $email, $recipient );
    //send_email();
}

The issue, of course, is that I need to pass the $email object by reference in order for it to replace the personalisation tags - but if I do that, the original object is changed and no longer contains the personalisation tags.

As I understand, clone won't help me here, because it'll only create a shallow copy: the content object inside the email object won't be cloned.

I've read about getting round this with unserialize(serialize($obj)) - but everything I've read says this is a big performance hit.

So, two finally get to my two questions:

  1. Is unserialize(serialize($obj)) a reasonable solution here?
  2. Or am I going about this whole thing wrong? Is there a different way that I can generate personalised copies of that email object?
like image 578
Wintermute Avatar asked May 31 '12 10:05

Wintermute


People also ask

How can I deep copy an object in PHP?

Using the assignment operator to copy an object In PHP, a shallow copy of the object can be created by using the keyword clone, and a deep copy of the object can be created by using the method __clone().

What is deep cloning in PHP?

Deep copies duplicate everything. A deep copy, meaning that fields are de-referenced: rather than references to objects being copied, new copy objects are created for any referenced objects, and references to these placed in new object. Shallow copies duplicate as little as possible.

Does clone () make a deep copy?

clone() is indeed a shallow copy. However, it's designed to throw a CloneNotSupportedException unless your object implements Cloneable . And when you implement Cloneable , you should override clone() to make it do a deep copy, by calling clone() on all fields that are themselves cloneable.

Does PHP support object cloning?

The clone keyword is used to create a copy of an object. If any of the properties was a reference to another variable or object, then only the reference is copied. Objects are always passed by reference, so if the original object has another object in its properties, the copy will point to the same object.


2 Answers

You could add a __clone() method to your email class. Which is automatically called when an instance of this class is cloned via clone(). In this method you can then manually add the template.

Example:

class Email {
    function __clone() {
        $this->template = new Template();
    }
}

.

unserialize(serialize($object)); // would be another solution...
like image 91
powtac Avatar answered Oct 05 '22 04:10

powtac


Another more generic and powerful solution: MyCLabs\DeepCopy.

It helps creating deep copy without having to overload __clone (which can be a lot of work if you have a lot of different objects).

like image 25
Matthieu Napoli Avatar answered Oct 05 '22 03:10

Matthieu Napoli