先贴出来最终结果:
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