克隆无法正常工作,该怎么办?

4

我有一个名为$objDummy的对象,属于某个名为ClassDummy的类,还有另外一个对象:

$objClone = clone $objDummy;

然后我在$objClone中做出任何更改,$objDummy也会发生变化。 我不想这样做。 如何让这个工作起来?

编辑: 回复Chris。 这是一个例子。

<?php
class myAnotherObject{
    public $myAnotherVar =10;
}

class myObject {
    public $myVar = false;
    function __construct() {
        $this->myVar = new myAnotherObject();
    }
}


$nl = "\n";
//*
$nl = '<br />';
//*/


$obj1 = new myObject();
echo 'obj1->myVar->myAnotherVar: '.$obj1->myVar->myAnotherVar;

$obj2 = clone $obj1;

echo $nl.'obj1->myVar->myAnotherVar: '.$obj1->myVar->myAnotherVar.', obj2->myVar->myAnotherVar: '.$obj2->myVar->myAnotherVar;

$obj2->myVar->myAnotherVar = 20;
echo $nl.'obj1->myVar->myAnotherVar: '.$obj1->myVar->myAnotherVar.', obj2->myVar->myAnotherVar: '.$obj2->myVar->myAnotherVar;

输出结果为:
obj1->myVar->myAnotherVar: 10
obj1->myVar->myAnotherVar: 10, obj2->myVar->myAnotherVar: 10
obj1->myVar->myAnotherVar: 20, obj2->myVar->myAnotherVar: 20

1
只是一个小提示:()括号在克隆时不需要,因为它不是一个函数,而更像“new”运算符。 - edorian
3个回答

11
你是否实现了__clone()方法?在PHP克隆文档的示例中,会比我能说得更清楚。具体而言,你需要关注以下部分:

当对象被克隆时,PHP 5将对所有对象属性执行浅复制。任何是其他变量的引用的属性将保持为引用。

克隆完成后,如果定义了__clone()方法,则会调用新创建对象的__clone()方法,以允许进行必要的属性更改。

更新
根据你对问题的更新,你确实缺少实现__clone()的步骤。由于myObject类的$myVar成员本身是一个对象,因此你还需要对其进行克隆。下面是myObject类的样式:
class myObject {
    public $myVar = false;
    function __construct() {
        $this->myVar = new myAnotherObject();
    }

    function __clone() {
        $this->myVar = clone $this->myVar;
    }
}
输出结果如下:
obj1->myVar->myAnotherVar: 10
obj1->myVar->myAnotherVar: 10, obj2->myVar->myAnotherVar: 10
obj1->myVar->myAnotherVar: 10, obj2->myVar->myAnotherVar: 20

1
请仔细检查问题。并告诉我如何获得解决方案。 - Gaurav
哇,这个解决方案真的很简单。我一定要仔细阅读文档。无论如何,感谢你的帮助。 - Gaurav

0

我无法复制您的结果。使用下面的代码,我得到了预期的输出(复制在代码下面)。___clone()方法对此不是必需的,如所示。您能否发布您代码的精简版本?

代码

class myObject {
    public $myVar = false;
    function __construct($newVar=5) {
        $this->myVar = $newVar;
    }
}

$nl = "\n";
//*
$nl = '<br />';
//*/


$obj1 = new myObject(10);
echo 'obj1->myVar: '.$obj1->myVar;

$obj2 = clone $obj1;
echo $nl.'obj1->myVar: '.$obj1->myVar.', obj2->myVar: '.$obj2->myVar;

$obj1->myVar = 20;
echo $nl.'obj1->myVar: '.$obj1->myVar.', obj2->myVar: '.$obj2->myVar;

输出

obj1->myVar: 10
obj1->myVar: 10, obj2->myVar: 10
obj1->myVar: 20, obj2->myVar: 10

经过讨论后进行了编辑:

你的问题是由于对一个对象的引用引起的。由于所有对象都是通过引用处理的,当你克隆一个对象时,你还需要克隆任何内部持有的对象,否则你最终会得到对单个对象的引用。

代码

class myAnotherObject{
    public $myAnotherVar =10;
}

class myObject {
    public $myVar = false;
    function __construct() {
        $this->myVar = new myAnotherObject();
    }
    function __clone() {
        $this->myVar = clone $this->myVar;  
    }
}


$nl = "\n";
//*
$nl = '<br />';
//*/


$obj1 = new myObject();
echo 'obj1->myVar->myAnotherVar: '.$obj1->myVar->myAnotherVar;

$obj2 = clone $obj1;

echo $nl.'obj1->myVar->myAnotherVar: '.$obj1->myVar->myAnotherVar.', obj2->myVar->myAnotherVar: '.$obj2->myVar->myAnotherVar;

$obj2->myVar->myAnotherVar = 20;
echo $nl.'obj1->myVar->myAnotherVar: '.$obj1->myVar->myAnotherVar.', obj2->myVar->myAnotherVar: '.$obj2->myVar->myAnotherVar;

输出

obj1->myVar->myAnotherVar: 10
obj1->myVar->myAnotherVar: 10, obj2->myVar->myAnotherVar: 10
obj1->myVar->myAnotherVar: 10, obj2->myVar->myAnotherVar: 20

@Rich Adams是正确的。我会编辑我的答案来演示。__clone()方法会好好照顾你的。 :) - Chris Baker

0
你可以这样做,但不适用于具有方法的对象。
function cloneObj(&obj) {
 return json_decode(json_encode($obj));
}

$a = new stdClass();
$b = cloneObj($a);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接