Reference link:
1. php.net official website documentation - object copy
When to use it? Excerpted from php.net:
In most cases, we do not need to completely copy an object to obtain its properties. But there is one case where it is really needed: if you have a GTK window object that holds window-related resources. You may want to copy a new window, keeping all the same properties as the original window, but it must be a new object (because if it is not a new object, changes in one window will affect the other window). There is another situation: if object A stores a reference to object B, when you copy object A, and you want the object used in it to be no longer object B but a copy of B, then you must get a copy of object A. .
Try to use the simplest "="
The first thing to make clear is: PHP objects are stored with an identifier, so the direct "assignment" behavior to the object is equivalent to "passing by reference"
<?php function dump($var){ var_dump($var); echo "<br/>"; } class A{ private $a; protected $b; public $c; public function d(){ echo "A -> d"; } } $a1 = new A(); $a2 = $a1; $a3 = new A(); dump($a1); dump($a2); dump($a3);
The output result is:
object(A)#1 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } object(A)#1 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } object(A)#2 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL }
It can be noticed that #n as the object identifier shows that $a1 and $a2 actually point to the same object, while $a3 is another object
So, if you need to copy an identical and brand-new object, you cannot copy it directly through =, otherwise changing $a1->a is equivalent to modifying $a2->a.
Shallow copy
In PHP5, there is a magic method __clone() in the class, which will be automatically called when used with the clone keyword and object (if not explicitly defined, an empty method will be called).
The function of the clone keyword is to copy an object to form a "shallow copy" of the object, and then assign it to the new object. At this time, the object identifier is different!
<?php function dump($var){ var_dump($var); echo "<br/>"; } class B{ public $d; } class A{ public $a; public $b; public function d(){ echo "A -> d"; } } $a1 = new A(); $a1->a = 123; // 这里对象属性的值是一个对象示例,其实就是存储了对象标识符。使用clone关键字生成的拷贝中的b属性仍然指向旧对象的b属性指向的对象,这是"浅拷贝"出现的问题。如果需要指向一个新的对象,必须"深拷贝" $a1->b = new B(); // PHP 5 only $a2 = clone $a1; dump($a1); dump($a2);
The output result is:
object(A)#1 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } object(A)#3 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } }
As you can see, $a1 and $a2 are obviously two different objects (the object identifiers are different). But one thing to note is that the object identifiers pointed to by "b" are both #2, which proves that the two objects are the same. This is the "flaw" of "shallow copy" - but sometimes these two objects do need The same, so PHP's clone defaults to "shallow copy".
Why is it called shallow copy?
Because when copying, all attributes are "passed by value", and the b attribute above stores the object identifier, so it is equivalent to "passing by reference". This is not a complete copy, so it is called "Shallow copy".
Deep copy
As mentioned above, when using the clone keyword, the __clone() method of the old object will be automatically called (and then the copied object will be returned), so you only need to rewrite the __clone() method in the corresponding class to make the returned The "pass-by-reference" property in an object points to another new object. The following is an example (you can compare the example of "shallow copy", which actually requires more steps to rewrite __clone()):
<?php function dump($var){ var_dump($var); echo "<br/>"; } class B{ public $d; } class A{ public $a; public $b; public function d(){ echo "A -> d"; } public function __clone(){ // clone自己 $this->b = clone $this->b; } } $a1 = new A(); $a1->a = 123; // 这里对象属性的值是一个对象示例,其实就是存储了对象标识符。使用clone关键字生成的拷贝中的b属性仍然指向旧对象的b属性指向的对象,这是"浅拷贝"出现的问题。如果需要指向一个新的对象,必须"深拷贝" $a1->b = new B(); // PHP 5 only $a2 = clone $a1; dump($a1); dump($a2);
The result is different, pay attention to the object identifier of the b attribute:
object(A)#1 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } object(A)#3 (2) { ["a"]=> int(123) ["b"]=> object(B)#4 (1) { ["d"]=> NULL } }