据我所知,php复制对象有以下三种方式:
<?php
class a{
public $v = 1;
}
$obj = new a();
// 1. clone方式
// $copy_obj = clone $obj;
// 2. 标识赋值方式
// $copy_obj = $obj;
// 3. 引用赋值方式
// $copy_obj = &$obj;
$copy_obj->v = 2;
echo '原对象的v属性等于' . $obj1->v;
echo '<br />';
echo '复制对象的v属性等于' . $obj2->v;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
三者详细区别不谈,这里只说clone方式,clone后的对象与原对象互不影响。那么,这有什么作用呢?什么时候应该想起要用clone呢?
举一个例子,有如下数据表score_form
id stud_id subject score …
1 1 chinese 90 …
2 1 math 95 …
3 1 English 96 …
… … … … …
需求是查询stud_id为1的学生的语文,数学,英语的成绩,很直观想出的是
ScoreForm::find()->where(['stud_id' => 1, 'subject' => 'chinese'])->one();
ScoreForm::find()->where(['stud_id' => 1, 'subject' => 'math'])->one();
ScoreForm::find()->where(['stud_id' => 1, 'subject' => 'English'])->one();
1
2
3
似乎没问题,对简单的查询来说确实没问题,但实际环境下,肯定有很多关联查询的,如学生表要关联吧,其他字段也可能要关联,即三次查询,要执行很多where判断,关联查询,其中只有subject这个查询条件不同,这时可以考虑用clone,代码如下:
$query = ScoreForm::find()->where(['stud_id' => 1]); // 还有其他where判断,关联查询...
$q1 = clone $query; $q2 = clone $query;
$query->andWhere(['subject' => 'chinese'])->one();
$q1->andWhere(['subject' => 'math'])->one();
$q2->andWhere(['subject' => 'English'])->one();
1
2
3
4
5
这样的好处是,不用重复写前面的查询条件~
代码是以yii2框架为例,其他框架数据库查询方式也差不多吧。
这个例子可能有些牵强,原场景很难复述,意思懂就行~~
总结
clone得出的对象不影响原对象
当要通过对象执行多次差异很小操作时,可以考虑先new 一个对象执行相同部分,再克隆多个对象,执行差异化部分。
---------------------
https://blog.csdn.net/kbellx/article/details/80264623
php5中默认通过引用传递对象,假设$obj1和$obj2是两个对象,使用$obj2=$obj1这样的方法复制出来的对象是相关联的,如果在程序中需要复制出一个值和原来相同的对象又不希望复制出来的对象与源对象相关联,那么就需要使用clone关键字,类似于$obj2=clone $obj1; 如果还希望在复制的同时,目标对象的某些属性与源对象的不同,可以在类里面定义一个__clone()方法,在这个方法中完成为目标对象的属性赋新值。
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/9/25
* Time: 22:11
*/
class doclone{
private $id,$name,$address;
public function __construct($id=0,$name='',$address=''){
$this->name=$name;
$this->id=$id;
$this->address=$address;
}
public function get_id(){
return $this->id;
}
public function get_name(){
return $this->name;
}
public function get_address(){
return $this->address;
}
public function __clone(){
$this->id=$this->id+1;
$this->name='Kong';
$this->address='USA';
}
}
$A = new doclone(10,'A','UK');
echo '克隆之前的对象:';
echo 'id='.$A->get_id();
echo 'name='.$A->get_name();
echo 'address='.$A->get_address();
echo "\n";
$B = clone $A;
echo '克隆过后的对象:';
echo 'id='.$A->get_id();
echo 'name='.$A->get_name();
echo 'address='.$A->get_address();
echo "\n";
echo '克隆过后的对象属性:';
echo 'id='.$B->get_id();
echo 'name='.$B->get_name();
echo 'address='.$B->get_address();
从执行结果可以看出,使用了clone之后,复制出的对象属性在__clone方法中重新设置,并且源对象A和目标对象B不再有任何关联。
---------------------
https://blog.csdn.net/bulbboy/article/details/82846033