PHP:检查对象是否是克隆(任何对象)


PHP: Check whether object is clone (of any object) or not?

class Object {}
$object = new Object();
$clone  = clone $object;
// no!
printf("%d'n", $object == $clone);
printf("%d'n", $object === $clone);
// no! no no..
printf("%d'n", $object instanceof $clone);
printf("%d'n", $clone instanceof $object);
// cos, this is true
printf("%d'n", $object instanceof $object);
printf("%d'n", $clone instanceof $clone);
// maybe something like this..
printf("%d'n", $clone cloneof $object);
printf("%d'n", cloneof($clone, $object));

实际上,我的问题是,"如何检测克隆某个对象的对象"。

经过一番搜索,我一无所获。因此,欢迎分享我的简单解决方案和任何其他答案/评论。

class Object
{
    private static $__hashes = [];
    public function __clone() {
        self::$__hashes[] = spl_object_hash($this);
    }
    public function isCloneOf($object) {
        return ($this == $object && $this !== $object
                && in_array(spl_object_hash($this), $object::$__hashes));
    }
}
$object = new Object();
$clone1 = clone $object;
$clone2 = clone $object;
printf("%d'n", $clone1->isCloneOf($object)); // 1
printf("%d'n", $clone2->isCloneOf($object)); // 1
printf("%d'n", $object->isCloneOf($object)); // 0
printf("%d'n", $object->isCloneOf($clone1)); // 0
printf("%d'n", $object->isCloneOf($clone2)); // 0
printf("%d'n", $clone1->isCloneOf(new stdClass())); // 0
$foo = $clone1;
$bar =& $clone1;
printf("%d'n", $foo->isCloneOf($object)); // 1
printf("%d'n", $bar->isCloneOf($object)); // 1

问题

// if I do this
$clone1->a = 1;
// then result will be false
printf("%d'n", $clone1->isCloneOf($object)); // 0
// if I do this (so must be same all vars in objects)
$clone1->a = 1;
$object->a = 1;
printf("%d'n", $clone1->isCloneOf($object)); // 1
// could not solve (giving up)..
$clone1clone = clone $clone1;
printf("%d'n", $clone1clone->isCloneOf($clone1)); // 1
printf("%d'n", $clone1->isCloneOf($clone1clone)); // 1

这个怎么样

class Object
{
    private $id = null;
    private $instance = null;
    private $cloneOf = null;
    public function __construct()
    {
        $this->id = uniqid();
        $this->instance = $this;
    }
    public function __clone()
    {
        $this->cloneOf = $this->instance;
        $this->instance = $this;
        $this->id = uniqid();
    }
    public function isCloneOf($object)
    {
        if (!($object instanceof Object))
            return false;
        $isClone = ($object->getId() === $this->cloneOf->getId());
        if ($isClone)
            return true;
        $cloneSource = $object->getCloneSource();
        if ($cloneSource)
            return $this->isCloneOf($cloneSource);
        return false;
    }
    public function getId()
    {
        return $this->id;
    }
    public function getCloneSource()
    {
        return $this->cloneOf;
    }
}

另一种选择:

function isCloneOf($object) {
    return empty(array_diff((array)$object, (array)$this));
}