How to copy data in PHP

#1

Followed another thema, I just would to say a coulpe words.

If we have some data structure with arrays and objects, then to make “pure” copy of this structure - really untrivial thing in PHP. I mean, if we would to create copy, where exists no any double reference on same object.

The first attempt of many developers - use operator clone. No any chance… clone makes no recursive cloning and if we have object property of reference type, just reference, but not instance itself will be cloned.

Of course, there is a magic method __clone, that could to make recursive cloning. But one more time, we have some unknown structure, and can’t to change it. So, forget about. clone is wrong way.

Next variant - serializing. Seems very easy: $copy = unserialize(serialize($obj)).

Potential problem is: serializing/unserializing events trigger two magic methods: __sleep and __wakeup. And if some of this methods is private, then we get an error. Actually developer could to make one of this methods private exactly to avoid cloning.

Practically, we have just one way to solve this problem - use ReflectionClass. ReflectionClass is meta class that could have an access to any class member, even private. So we could create followed algorithm…

  1. Method expand($source) recursivelly creates array from data structure. All objects in this array will be replaced also with arrays that have some service members, e.g. object’s class. With help of this service members we could make structure restore.

  2. Method fold($contents) get array from p.1 and creates new data structure - pure copy of original.

Is that so easy? Sorry, but not. Problem is: data structure could be not only tree, where exists just one kind of references - parent to child. In real structure it could be recursive reference - child to parent and also another crossing reference from two objects on same third object. And if we ignore this, we could have two instances instead of same, or even unlimited recursion and execution fail.

But this problem can be solved. We just should to describe with our service members, whether this instance should be created or enough to get it from registry.

For example, here is my classes, that make copy from PHP objects/data structures…