Come faccio a creare una copia di un oggetto in PHP?
-
06-07-2019 - |
Domanda
Sembra che in PHP gli oggetti vengano passati per riferimento. Persino gli operatori di assegnazione non sembrano creare una copia dell'oggetto.
Ecco una semplice prova inventata:
<?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 entrambi i casi di stampa ricevo 'dopo'
Quindi, come passo $ a a set_b() per valore, non per riferimento?
Soluzione
In PHP 5+ gli oggetti vengono passati per riferimento. In PHP 4 vengono passati in base al valore (ecco perché ha avuto un tempo di esecuzione per riferimento, che è diventato obsoleto).
Puoi usare l'operatore 'clone' in PHP5 per copiare oggetti:
$objectB = clone $objectA;
Inoltre, sono solo gli oggetti che vengono passati per riferimento, non tutto come hai detto nella tua domanda ...
Altri suggerimenti
Le risposte si trovano comunemente nei libri di Java.
-
clonazione: Se non si ignora il metodo clone, il comportamento predefinito è copia superficiale. Se i tuoi oggetti hanno solo variabili membro primitive, è del tutto ok. Ma in un linguaggio non tipizzato con un altro oggetto come variabili membro, è un mal di testa.
-
serializzazione / deserializzazione
$ new_object = unserialize (serialize ($ your_object))
Ciò consente di ottenere copie profonde con un costo elevato a seconda della complessità dell'oggetto.
Secondo il commento precedente, se si dispone di un altro oggetto come variabile membro, procedere come segue:
class MyClass {
private $someObject;
public function __construct() {
$this->someObject = new SomeClass();
}
public function __clone() {
$this->someObject = clone $this->someObject;
}
}
Ora puoi fare la clonazione:
$bar = new MyClass();
$foo = clone $bar;
Secondo i documenti ( http://ca3.php.net/language.oop5. clonazione ):
$a = clone $b;
Solo per chiarire PHP usa copia su scrittura, quindi praticamente tutto è un riferimento fino a quando non lo modifichi, ma per gli oggetti devi usare clone e il metodo magico __clone () come nella risposta accettata.
Questo codice aiuta a clonare metodi
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());
Stavo facendo dei test e ho ottenuto questo:
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" }
?>
In questo esempio creeremo la classe iPhone e ne faremo una copia esatta clonando
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>";
Se si desidera copiare completamente le proprietà di un oggetto in un'istanza diversa, è possibile utilizzare questa tecnica:
Serializzalo su JSON e poi ridenializza nuovamente in Object.