先贴出来最终结果:
public function deepClone($obj){
$serObj = base64_encode(gzcompress(serialize($obj)));
return unserialize(gzuncompress(base64_decode($serObj)));
}问题:为什么需要深克隆?因为我们有时候需要保持对象的属性,以及对象的属性【PS:该属性也是个对象】,这时候如果做赋值操作,那么就仅仅是当前对象的引用,那么A=B,B发生了变化,A自动发生了变化!
废话少说,看案例:
<?php
echo "<br><br>====================值赋值=====================<br><br>";
$old = 1;
$new = $old;
$new = 2;
echo "1、old:".$old."<br/>";//1、old:1
echo "2、new:".$new."<br/>";//2、new:2
$old = 3;
echo "1、old:".$old."<br/>";//1、old:3
echo "2、new:".$new."<br/>";//2、new:2
【总结】:值赋值很正常,和我们想的应该一样
echo "<br><br>=====================对象赋值====================<br><br>";
class objInside{
public $attrInside = 1;
}
$old = new objInside();
$new = $old;
$new->attrInside = 2;
echo "1、old:".$old->attrInside."<br/>";//1、old:2
echo "2、new:".$new->attrInside."<br/>";//2、new:2
$old->attrInside = 3;
echo "1、old:".$old->attrInside."<br/>";//1、old:3
echo "2、new:".$new->attrInside."<br/>";//2、new:3
【总结】:对象赋值,是不是感觉有点不一样,这里其实是引用
echo "<br><br>=====================对象属性克隆====================<br><br>";
class objInsideClone{
public $attrInside = 1;
}
$old = new objInsideClone();
$new = clone $old;
$new->attrInside = 2;
echo "1、old:".$old->attrInside."<br/>";//1、old:1
echo "2、new:".$new->attrInside."<br/>";//2、new:2
$old->attrInside = 3;
echo "1、old:".$old->attrInside."<br/>";//1、old:3
echo "2、new:".$new->attrInside."<br/>";//2、new:2
【总结】:对象clone,是我们想要的效果是吧,这里才是创建副本
echo "<br><br>=====================对象-对象属性克隆【没有colne函数】====================<br><br>";
class objInsideClone2{
public $attrInside = 1;
}
class objOutsideClone2{
public $objInside2 = null;
public function __construct(){
$this->objInside2 = new objInsideClone2();
}
//public function __clone(){//【没有colne函数】
// $this->objInside2 = clone $this->objInside2;
//}
}
$old = new objOutsideClone2();
$new = clone $old;
$new->objInside2->attrInside = 2;
echo "1、old:".$old->objInside2->attrInside."<br/>";//1、old:2
echo "2、new:".$new->objInside2->attrInside."<br/>";//2、new:2
$old->objInside2->attrInside = 3;
echo "1、old:".$old->objInside2->attrInside."<br/>";//1、old:3
echo "2、new:".$new->objInside2->attrInside."<br/>";//2、new:3
【总结】:这里是不是有点懵逼,刚刚上面的demo,普通属性可以clone过来,但是为什么这里对象属性clone不过来呢?
echo "<br><br>=====================对象-对象属性克隆【有colne函数】====================<br><br>";
class objInsideClone2{
public $attrInside = 1;
}
class objOutsideClone2{
public $objInside2 = null;
public function __construct(){
$this->objInside2 = new objInsideClone2();
}
public function __clone(){//【有colne函数】
$this->objInside2 = clone $this->objInside2;
}
}
$old = new objOutsideClone2();
$new = clone $old;
$new->objInside2->attrInside = 2;
echo "1、old:".$old->objInside2->attrInside."<br/>";//1、old:1
echo "2、new:".$new->objInside2->attrInside."<br/>";//2、new:2
$old->objInside2->attrInside = 3;
echo "1、old:".$old->objInside2->attrInside."<br/>";//1、old:3
echo "2、new:".$new->objInside2->attrInside."<br/>";//2、new:2
【总结】:现在明白了吧,如果要赋值对象属性,是需要添加__clone方法;这样是不是很复杂呢?因为很多时候我们利用的别人已经写好的东西
【大中型项目】都是好多年的代码了,要加起来恐怕没那么容易
超级宇宙无敌,深度克隆,通过序列化和反序列的方式:
public function deepClone($obj){
$serObj = base64_encode(gzcompress(serialize($obj)));
return unserialize(gzuncompress(base64_decode($serObj)));
}参考文章:
1、https://blog.csdn.net/lovelion/article/details/7424620
2、https://www.cnblogs.com/taijun/p/4208008.html【PS:文章末尾有个错误,用json_encode无法独立完成该任务,当然序列化+json_encode是可以的】
public function deepClone($obj){
$serObj = json_encode(serialize($obj));
return unserialize(json_decode($serObj));
}//但是核心是序列化3、针对参考2的错误【https://www.cnblogs.com/jiaoaozuoziji/p/7390021.html】见json_encode和序列化之间的区别
4、注意【gzcompress用法】https://blog.csdn.net/mangrandi/article/details/81780720