如何在PHP中创建对象的副本?

Nic*_*tes 151 php clone copy shallow-copy

看来PHP对象是通过引用传递的.甚至赋值运算符似乎也没有创建Object的副本.

这是一个简单,人为的证明:

<?php

class A {
    public $b;
}


function set_b($obj) { $obj->b = "after"; }

$a = new A();
$a->b = "before";
$c = $a; //i would especially expect this to create a copy.

set_b($a);

print $a->b; //i would expect this to show 'before'
print $c->b; //i would ESPECIALLY expect this to show 'before'

?>
Run Code Online (Sandbox Code Playgroud)

在两个印刷案例中,我都在"追求"

那么,我如何通过值传递$ aset_b(),而不是通过引用?

Era*_*rin 256

在PHP 5+对象通过引用传递.在PHP 4中,它们通过值传递(这就是为什么它通过引用传递运行时,它被弃用).

您可以使用PHP5中的'clone'运算符来复制对象:

$objectB = clone $objectA;
Run Code Online (Sandbox Code Playgroud)

此外,它只是通过引用传递的对象,而不是你在问题中所说的所有内容......

  • 纠正一个常见的误解(我认为即使PHP文档也错了!)PHP 5的对象不是"通过引用传递".与在Java中一样,它们具有*附加*级别的间接 - 变量指向"对象指针",并指向对象.因此,两个变量可以指向同一个对象*,而不是*引用相同的值.从这个例子中可以看出:`$ a = new stdClass; $ b =&$ a; $ a = 42; var_export($ b);`here` $ b`是对*变量*`$ a`的引用; 如果用正常的`=`替换`=&`,它不是*引用,仍然指向原始对象. (17认同)

yog*_*man 97

答案常见于Java书籍.

  1. 克隆:如果不重写克隆方法,则默认行为是浅拷贝.如果你的对象只有原始成员变量,那就完全可以了.但是在使用另一个对象作为成员变量的无类型语言中,这是一个令人头痛的问题.

  2. 序列化/反序列化

$new_object = unserialize(serialize($your_object))

这取决于对象的复杂性,以高成本实现深拷贝.

  • +1非常好,很棒,很棒的方式在PHP中执行DEEP复制,非常简单.让我来问你一些关于PHP clone关键字提供的标准浅拷贝,你说只有原始成员变量被复制:PHP数组/字符串被认为是原始成员变量,所以它们被复制了,我是对的吗? (4认同)
  • 对于任何选择它的人:一个"浅"副本(`$ a = clone $ b`,没有魔术`__clone()`方法在玩)相当于在术语中查看对象`$ b`的每个属性,并使用`=`分配给同一类的新成员中的相同属性.作为对象的属性不会得到`clone`d,也不会得到数组中的对象; 对于通过引用约束的变量也是如此; 其他一切只是一个值,并像任何任务一样被复制. (3认同)
  • 完善!json_decode(json_encode($ OBJ)); 不克隆私有/受保护的属性和任何方法...反序列化(序列化也不克隆方法... (3认同)
  • 这增加了**大量**的运行时开销。您将对象序列化为字符串,然后将该字符串解析回新变量。虽然这可以实现您想要做的事情,但它的速度非常慢。您不仅使用时间和内存将所有对象转换为字符串并返回,还破坏了 PHP 可能的 CopyOnWrite 机制。更好的方法是按照下面 /sf/answers/13033401/ 的建议正确实现“__clone”方法。请参阅 http://www.phpinternalsbook.com/php5/zvals/memory_management.html 以获得深入的解释 (2认同)

Sta*_*lav 19

根据之前的评论,如果您有另一个对象作为成员变量,请执行以下操作:

class MyClass {
  private $someObject;

  public function __construct() {
    $this->someObject = new SomeClass();
  }

  public function __clone() {
    $this->someObject = clone $this->someObject;
  }

}
Run Code Online (Sandbox Code Playgroud)

现在你可以做克隆:

$bar = new MyClass();
$foo = clone $bar;
Run Code Online (Sandbox Code Playgroud)


Pat*_*ssi 5

只是为了澄清 PHP 使用写时复制,所以基本上所有内容都是引用,直到您修改它,但是对于对象,您需要使用克隆和 __clone() 魔术方法,就像接受的答案中一样。