我有一个对象(称为a),它包含另外两个对象的数组(称为b)。我正在尝试克隆该对象(a)。当我克隆对象时,我还想克隆其他两个对象。但是,当我运行代码来更改原始对象(a)数组中的子对象(b)时,它还会使用克隆对象(a)中的对象(b)更改数组。我该如何防止这种情况?这是我的代码:
<?php
class a{
public $b = array();
function __clone(){
foreach($this->b AS $key => $b){
$this->b[$key] = clone $b;
}
}
function addB($name,$b){
$b->setA($this);
$this->b[$name] = $b;
}
}
class b{
public $a;
public $var = 'no';
function execute(){
$this->var = 'yes';
}
function seeB1(){
return $this->a->b['b1']->var;
}
function setA($a){
$this->a = $a;
}
}
$a1 = new a;
$b1 = new b;
$b2 = new b;
$a1->addB('b1',$b1);
$a1->addB('b2',$b2);
//Clones A
$a2 = clone $a1;
$a1->b['b1']->execute();
var_dump($a1->b['b2']->seeB1()); //This should say Yes. It does
var_dump($a2->b['b2']->seeB1()); //This should say No. It says Yes
?>
输出结果为:
string 'yes' (length=3)
string 'yes' (length=3)
我想用这个脚本做的是克隆A.在克隆A之后,我运行原始b1的函数execute()来改变$ var。然后我从原始b2查看原始b1。这表明原始b1的$ var已经改变了,应该是这样。但是,如果我从克隆的b1查看克隆的b1,它还会显示$ var已更改。它不应该。
我做错了什么?
问候,汤姆。
答案 0 :(得分:2)
您可以尝试使用以下内容替换__clone函数:
function __clone() {
foreach ($this as $key => $value) {
if (is_object($value) || (is_array($value))) {
$this->{$key} = unserialize(serialize($value));
}
}
}
通过使用serialize / unserialize方法,您肯定会避免更改对象的原始属性。
经过测试,它适用于简单对象,例如示例中的对象。