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

时间:2014-12-23 22:31:03

标签: php oop object clone

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));

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

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分: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;
    }
}

答案 2 :(得分:0)

另一种选择:

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