克隆PHP中所有实体的对象

时间:2015-01-30 15:56:45

标签: php object clone circular-reference

如何在PHP中clone对象包含所有数据?

所以,澄清:"包含所有整个数据"意味着我需要真正复制实例中的任何对象。例如,如果您有:

class Bar 
{
    public $indicator;
    public function __construct($x)
    {
        $this->indicator = $x;
    }
}
class Foo 
{
    protected $prop;
    public function __construct(Bar $prop) 
    {
        $this->prop = $prop;
    }

    public function getProp()
    {
        return $this->prop;
    }
}

$objX = new Foo(new Bar('one'));
$objY = clone $objX;
$objY->getProp()->indicator = 'two';

//two, since cloned object still tracks references inside it:
echo $objX->getProp()->indicator; 

上面代码的小提琴你可以找到here

没关系......

因为标准__clone()只会复制主对象本身:

  

当克隆一个对象时,PHP 5将执行所有的浅层副本   对象的属性。任何引用其他的属性   变量,仍然是参考。

所以它不会跟踪内部的所有实体,因为它会非常慢。但现在,我需要这样做。

用例是:当我测试我的代码时,我正在为phpunit的可调用匹配器提供值存储。但是,该存储是方法名称,参数值和结果值之间的简单映射。一切都很好,除非我需要两次使用相同的map值 - 因为在下一次迭代时它可能会被测试的代码修改。这是一个问题。

天真的方法

到目前为止,我做到了这一点:

public static function cloneArrayContainer(array $data)
{
    $result = [];
    foreach ($data as $key => $value) {
        if (is_object($value)) {
            $result[$key] = self::cloneObjectContainer($value);
        } else if (is_array($value)) {
            $result[$key] = self::cloneArrayContainer($value);
        } else {
            $result[$key] = $value;
        }
    }
    return $result;
}

public static function cloneObjectContainer($object)
{
    $result     = clone $object;
    $reflection = new \ReflectionObject($object);
    foreach ($reflection->getProperties() as $property) {
        $property->setAccessible(true);
        $value = $property->getValue($result);
        if (is_object($value)) {
            $property->setValue($result, self::cloneObjectContainer($value));
        } elseif (is_array($value)) {
            $property->setValue($result, self::cloneArrayContainer($value));
        }
    }
    return $result;
}

在一个存根助手中。但它在循环引用(显然)上失败了,遗憾的是,在我的情况下无法避免,因为它们对我的应用程序是有效的(并且是业务逻辑要求的)对象。

有什么想法吗?

我也试过unserialize() / serialize() - 失败了,而且,我的对象里面可能有callables / resources,因此,一种方法不适合我的情况。目前,我正在考虑重新考虑结构本身(测试,我的意思) - 但这将是最后一件事,这意味着克隆方法失败。

0 个答案:

没有答案