1

In the given scenario, i have a class:

class shopCart {}

I use destructors and constructors in there, to perform certain actions.

Later on, i want to store a serialized version of the cart. However, the object i serialize should not incorporate the destructor and constructor methods.

In order to achieve this, i created a class:

class storageCart extends shopCart {
    function __construct(){}
    function __destruct(){}
}

Now, before i store the cart, i must create a new object of type storageCart and make sure it contains all the properties of shopCart.

To fulfill this need, shopCart has a method getInstanceForStorage():

public function getInstanceForStorage() {
    $storageCart = new storageCart();
    foreach(get_object_vars($this) as $k => $v){
        $storageCart->{$k}=$v;
    }
    return $storageCart;
}

The problem is that changes i make to the new instance (storageCart) seem to affect the original instance (shopCart).

It is important to mention here, that one of the variables of shopCart is an array containing objects (cart items).

I assume i ran into some object / instancing / copying / cloning (or lack thereof) mess. But i don't know what the problem could be, because i do not use pointers in my assignment in the above foreach loop.

Can anyone shed some light on what is happening here?

Note: This is PHP > 5.3

EDIT

I tried copying the contents of the array which contains the objects, by assigning them to the same array in the new object and using clone, but - to my surprise - i still end up with a reference. I don't understand.

Is it perhaps possible, that objects within the cloned objects are still references to the original objects?

SquareCat
  • 5,699
  • 9
  • 41
  • 75
  • Yes they are, you need to do a [deep clone](http://stackoverflow.com/questions/18592872/deep-cloning-an-object-clone-vs-serialize) if you want those properties to be clones rather than references – Mark Baker Jul 02 '15 at 20:22
  • Oh. Is it safe then, to recursively run through an object's properties, looking for deeper objects, and then copying clones onto themselves? – SquareCat Jul 02 '15 at 20:26
  • Perfectly safe, and the recommended technique in this case, because you're not copying them onto themselves, you're creating new clones instances within the clone.... the originals remain intact within the original parent – Mark Baker Jul 02 '15 at 20:29
  • Awesome. Mind posting as an answer so we can close this accordingly? – SquareCat Jul 02 '15 at 20:29

1 Answers1

1

The technique you want is called making a "deep clone", and can be implemented easily using the __clone() magic method in your objects:

/**
 * Implement PHP __clone to create a deep clone, not just a shallow copy.
 */
public function __clone()
{
    foreach ($this as $key => $val) {
        if (is_object($val) || (is_array($val))) {
            $this->{$key} = clone $val;
        }
    }
}

Just define this in your main class, and in the classes of all the objects that you store as properties in that class, all the way down

Of course, if you hold an array of objects as a property, you'll need to adapt this code to walk that array as well

Mark Baker
  • 209,507
  • 32
  • 346
  • 385