4

In PHP objects are automatically passed by reference:

$obj1 = new stdClass();
$obj1->foo = 'bar';
$obj2 = $obj1;
$obj2->foo = 'OOF';
var_dump($obj1->foo); // OOF

Is there an elegant way to copy that variable and NOT refer to the original variable? I want to store a copy of an object and then modify it without effecting the original. Thanks.

emersonthis
  • 32,822
  • 59
  • 210
  • 375
  • 3
    Just **clone** it! – Rizier123 Aug 04 '16 at 16:24
  • Why? What's the point of passing objects by value? BTW: Objects aren't really passed by reference, you actually pass the object identifier. Say you create an object, that instance is stored in memory and assigned an id (eg 123), passing that instance actually passes that id -by value- and the called function/method then retrieves that object using the identifier. A reference is slightly different: `$x = new stdClass; $y = &$x; $y = null; var_dump($x);` will dump `null` – Elias Van Ootegem Aug 04 '16 at 16:46
  • 1
    "Why?" <-- I don't understand this question. I want to modify a "copy" of the variable without effecting the original? Am I missing something? Is there something exotic about that use case? Ex: I want to store a list of objects and log them later but I don't need EVERY property. So I `clone` and `unset` a bunch of properties I don't need for debugging purposes. Make sense? – emersonthis Aug 04 '16 at 16:53
  • 1
    @emersonthis: Yes and no. If you don't need every property, and clone an instance (which is relatively expensive), _and_ unset some properties then IMO you're violating the SRP. The object you're logging has got its job to do _and_ has to know what properties should be logged. I would instead create a logging formatter or processor of sorts that filters out the things I don't want/need to log. That way, I don't keep 2 copies of an object in memory, and don't have the same tight coupling between logging and business logic – Elias Van Ootegem Aug 04 '16 at 16:58

1 Answers1

13

You can clone the object:

$obj2 = clone $obj1;

Note that $obj2 will be a shallow copy of $obj1. As stated in the PHP manual:

When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties. Any properties that are references to other variables will remain references.

You can override the __clone() method to manually clone any subobjects if you wish.

Viktor
  • 3,436
  • 1
  • 33
  • 42
  • Nice. I didn't know about this one. Thanks Viktor. +1 – BeetleJuice Aug 04 '16 at 16:26
  • Beware, it doesn't clone objects that are stored in properties of the cloned object. You need to clone them explicitly via `__clone` – Torben Aug 04 '16 at 16:28
  • @Torben What happens to properties that are objects when you clone? Do they just disappear in the copy? Or maybe they switch to `null`? – emersonthis Aug 04 '16 at 16:30
  • I did a quick test and it looks like the object property DID get copied. Maybe I misunderstood Torben's comment. – emersonthis Aug 04 '16 at 16:33
  • @Torben Oh I think you meant that the object property appears in the new copy... but it will still be a reference. In other words: the "clone magic" isn't applied recursively down to each property. Is that what you meant? – emersonthis Aug 04 '16 at 16:35
  • 1
    @emersonthis: yes, properties containing objects will still use the same access-through-identifier system. To recursively clone objects, you have to implement the magic `__clone` method yourself, to manually iterate over the properties that are objects, and clone them, too – Elias Van Ootegem Aug 04 '16 at 16:48
  • @emersonthis That's exactly what I meant :) – Torben Sep 07 '16 at 22:38