Как создать копию объекта в 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 значение set_b() по значению, а не по ссылке?
Ответы
Ответ 1
В PHP 5+ объекты передаются по ссылке. В PHP 4 они передаются по значению (то, почему он прошел через ссылку по ссылке, которая стала устаревшей).
Вы можете использовать оператор clone в PHP5 для копирования объектов:
$objectB = clone $objectA;
Кроме того, это просто объекты, которые передаются по ссылке, а не все, как вы сказали в своем вопросе...
Ответ 2
Ответы обычно встречаются в Java-книгах.
-
Клонирование:
Если вы не переопределяете метод clone, поведение по умолчанию - это мелкая копия. Если ваши объекты имеют только примитивные переменные-члены, все в порядке. Но на беспринципном языке с другим объектом в качестве переменных-членов это головная боль.
-
сериализации/десериализации
$new_object = unserialize(serialize($your_object))
Это обеспечивает глубокую копию с большой стоимостью в зависимости от сложности объекта.
Ответ 3
Согласно предыдущему комментарию, если у вас есть другой объект в качестве переменной-члена, выполните следующие действия:
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;
Ответ 4
В соответствии с документами (http://ca3.php.net/language.oop5.cloning):
$a = clone $b;
Ответ 5
Просто, чтобы уточнить, PHP использует копию для записи, поэтому в основном все ссылки, пока вы ее не модифицируете, но для объектов вам нужно использовать клон и магический метод __clone(), как в принятом ответе.
Ответ 6
Этот код помогает клонировать методы
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());
Ответ 7
Я тестировал и получил следующее:
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" }
?>
Ответ 8
В этом примере мы создадим класс 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>";
Ответ 9
Если вы хотите полностью скопировать свойства объекта в другом экземпляре, вы можете использовать эту технику:
Сериализуйте его в JSON, а затем де-сериализуйте его обратно в Object.