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

发布于 2024-07-07 04:18:31 字数 537 浏览 9 评论 0原文

看来在 PHP 中对象是通过引用传递的。 即使赋值运算符似乎也没有创建对象的副本。

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

<?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'

?>

在两种打印情况下,我都得到“after”

那么,如何将 $a 传递给 set_b()按价值,而不是按参考?

It appears that in PHP objects are passed by reference. Even assignment operators do not appear to be creating a copy of the Object.

Here's a simple, contrived proof:

<?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'

?>

In both print cases I am getting 'after'

So, how do I pass $a to set_b() by value, not by reference?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

墨落成白 2024-07-14 04:18:31

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

您可以使用 PHP5 中的“克隆”运算符来复制对象:

$objectB = clone $objectA;

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

In PHP 5+ objects are passed by reference. In PHP 4 they are passed by value (that's why it had runtime pass by reference, which became deprecated).

You can use the 'clone' operator in PHP5 to copy objects:

$objectB = clone $objectA;

Also, it's just objects that are passed by reference, not everything as you've said in your question...

清晰传感 2024-07-14 04:18:31

答案通常可以在 Java 书籍中找到。

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

  2. 序列化/反序列化

$new_object = unserialize(serialize($your_object))

这实现了深度复制,但根据对象的复杂性,成本很高。

The answers are commonly found in Java books.

  1. cloning:
    If you don't override clone method, the default behavior is shallow copy. If your objects have only primitive member variables, it's totally ok. But in a typeless language with another object as member variables, it's a headache.

  2. serialization/deserialization

$new_object = unserialize(serialize($your_object))

This achieves deep copy with a heavy cost depending on the complexity of the object.

苄①跕圉湢 2024-07-14 04:18:31

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

class MyClass {
  private $someObject;

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

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

}

现在您可以进行克隆:

$bar = new MyClass();
$foo = clone $bar;

According to the previous comment, if you have another object as a member variable, do the following:

class MyClass {
  private $someObject;

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

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

}

Now you can do cloning:

$bar = new MyClass();
$foo = clone $bar;
他夏了夏天 2024-07-14 04:18:31

根据文档(https://www.php.net/language.oop5.cloning):

$a = clone $b;

According to the docs (https://www.php.net/language.oop5.cloning):

$a = clone $b;
苄①跕圉湢 2024-07-14 04:18:31

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

Just to clarify PHP uses copy on write, so basically everything is a reference until you modify it, but for objects you need to use clone and the __clone() magic method like in the accepted answer.

没︽人懂的悲伤 2024-07-14 04:18:31

此代码有助于克隆方法

class Foo{

    private $run=10;
    public $foo=array(2,array(2,8));
    public function hoo(){return 5;}


    public function __clone(){

        $this->boo=function(){$this->hoo();};

    }
}
$obj=new Foo;

$news=  clone $obj;
var_dump($news->hoo());

This code help clone methods

class Foo{

    private $run=10;
    public $foo=array(2,array(2,8));
    public function hoo(){return 5;}


    public function __clone(){

        $this->boo=function(){$this->hoo();};

    }
}
$obj=new Foo;

$news=  clone $obj;
var_dump($news->hoo());
无人问我粥可暖 2024-07-14 04:18:31

我正在做一些测试并得到这个:

class A {
  public $property;
}

function set_property($obj) {
  $obj->property = "after";
  var_dump($obj);
}

$a = new A();
$a->property = "before";

// Creates a new Object from $a. Like "new A();"
$b = new $a;
// Makes a Copy of var $a, not referenced.
$c = clone $a;

set_property($a);
// object(A)#1 (1) { ["property"]=> string(5) "after" }

var_dump($a); // Because function set_property get by reference
// object(A)#1 (1) { ["property"]=> string(5) "after" }
var_dump($b);
// object(A)#2 (1) { ["property"]=> NULL }
var_dump($c);
// object(A)#3 (1) { ["property"]=> string(6) "before" }

// Now creates a new obj A and passes to the function by clone (will copied)
$d = new A();
$d->property = "before";

set_property(clone $d); // A new variable was created from $d, and not made a reference
// object(A)#5 (1) { ["property"]=> string(5) "after" }

var_dump($d);
// object(A)#4 (1) { ["property"]=> string(6) "before" }

?>

I was doing some testing and got this:

class A {
  public $property;
}

function set_property($obj) {
  $obj->property = "after";
  var_dump($obj);
}

$a = new A();
$a->property = "before";

// Creates a new Object from $a. Like "new A();"
$b = new $a;
// Makes a Copy of var $a, not referenced.
$c = clone $a;

set_property($a);
// object(A)#1 (1) { ["property"]=> string(5) "after" }

var_dump($a); // Because function set_property get by reference
// object(A)#1 (1) { ["property"]=> string(5) "after" }
var_dump($b);
// object(A)#2 (1) { ["property"]=> NULL }
var_dump($c);
// object(A)#3 (1) { ["property"]=> string(6) "before" }

// Now creates a new obj A and passes to the function by clone (will copied)
$d = new A();
$d->property = "before";

set_property(clone $d); // A new variable was created from $d, and not made a reference
// object(A)#5 (1) { ["property"]=> string(5) "after" }

var_dump($d);
// object(A)#4 (1) { ["property"]=> string(6) "before" }

?>
调妓 2024-07-14 04:18:31

在此示例中,我们将创建 iPhone 类,并通过克隆从中进行精确复制

class iPhone
{
    public $name;
    public $email;

    public function __construct($n, $e) {

       $this->name = $n;
       $this->email = $e;

    }
}

$main = new iPhone('Dark', '[email protected]');
$copy = clone $main;

// if you want to print both objects, just write this    

echo "<pre>"; print_r($main);  echo "</pre>";
echo "<pre>"; print_r($copy);  echo "</pre>";

In this example we will create iPhone class and make exact copy from it by cloning

class iPhone
{
    public $name;
    public $email;

    public function __construct($n, $e) {

       $this->name = $n;
       $this->email = $e;

    }
}

$main = new iPhone('Dark', '[email protected]');
$copy = clone $main;

// if you want to print both objects, just write this    

echo "<pre>"; print_r($main);  echo "</pre>";
echo "<pre>"; print_r($copy);  echo "</pre>";
む无字情书 2024-07-14 04:18:31

如果您想在不同实例中完全复制对象的属性,您可能需要使用此技术:

将其序列化为 JSON,然后将其反序列化回 Object。

If you want to fully copy properties of an object in a different instance, you may want to use this technique:

Serialize it to JSON and then de-serialize it back to Object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文