Comment créer une copie d'un objet en PHP?

Il semble qu'en PHP les objets soient passés par référence. Même les opérateurs d'affectation ne semblent pas créer une copie de l'objet.

Voici une preuve simple et artificielle:

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

?>

Dans les deux cas d'impression, je reçois 'après'

Donc, comment puis-je passer $a pour set_b() par valeur et non par référence?

128
demandé sur tereško 2008-10-09 08:21:03

9 réponses

En PHP 5 + les objets sont passés par référence. En PHP 4, ils sont passés par valeur (c'est pourquoi il avait un passage d'exécution par référence, qui est devenu obsolète).

Vous pouvez utiliser L'opérateur' clone ' dans PHP5 pour copier des objets:

$objectB = clone $objectA;

En outre, ce ne sont que des objets qui sont passés par référence, pas tout comme vous l'avez dit dans votre question...

221
répondu Eran Galperin 2008-10-09 04:24:09

Les réponses se trouvent généralement dans les livres Java.

  1. Le Clonage: Si vous ne remplacez pas la méthode clone, le comportement par défaut est shallow copy. Si vos objets n'ont que des variables membres primitives, c'est totalement ok. Mais dans un langage sans type avec un autre objet en tant que variables membres, c'est un casse-tête.

  2. La Sérialisation/désérialisation

$new_object = unserialize(serialize($your_object))

Cela permet d'obtenir une copie profonde avec un coût élevé en fonction de la complexité de l'objet.

79
répondu yogman 2015-08-03 16:30:09

Selon le commentaire précédent, si vous avez un autre objet en tant que variable membre, procédez comme suit:

class MyClass {
  private $someObject;

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

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

}

Maintenant, vous pouvez faire le clonage:

$bar = new MyClass();
$foo = clone $bar;
18
répondu Stanislav 2009-07-23 09:06:58

Selon les docs (http://ca3.php.net/language.oop5.cloning):

$a = clone $b;
9
répondu Leo 2013-08-28 01:10:10

Juste pour clarifier PHP utilise copy on write, donc fondamentalement tout est une référence jusqu'à ce que vous le Modifiez, mais pour les objets, vous devez utiliser clone et la méthode magique __clone() comme dans la réponse acceptée.

4
répondu Patricio Rossi 2015-05-06 00:36:36

CE Code aide les méthodes de clone

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());
1
répondu zloctb 2013-10-03 20:25:32

Je faisais des tests et j'ai eu ceci:

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

?>
1
répondu Pyetro 2014-01-23 19:29:00

Dans cet exemple, nous allons créer iPhone classe et de faire la copie exacte de celui-ci par clonage

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>";
0
répondu Muhammad Ebrahim 2017-11-03 16:59:36

Si vous souhaitez copier entièrement les propriétés d'un objet dans une instance différente, vous pouvez utiliser cette technique:

Sérialisez-le en JSON, puis désérialisez-le en objet.

-1
répondu diy_nunez 2016-02-23 21:00:16