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

在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美元传递给设置_B()呢?

153512 次浏览

According to the docs (http://ca3.php.net/language.oop5.cloning):

$a = clone $b;

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...

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.

According to previous comment, if you have another object as a member variable, do 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;

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.

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());

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" }


?>

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.

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', 'm@m.com');
$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>";