web-dev-qa-db-fra.com

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

Il semble que, dans PHP, les objets soient passés par référence. Même les opérateurs d’affectation ne semblent pas créer de 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'

Alors, comment puis-je passer $ a àset_b ()par valeur, pas par référence?

136
Nick Stinemates

Dans PHP 5+ objets sont passés par référence. Dans PHP 4, ils sont passés par valeur (c’est pourquoi le temps d’exécution passait par référence, ce qui est devenu obsolète).

Vous pouvez utiliser l'opérateur 'clone' en PHP5 pour copier des objets:

$objectB = clone $objectA;

De plus, ce ne sont que des objets qui sont passés par référence, pas tout ce que vous avez dit dans votre question ...

239
Eran Galperin

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

  1. clonage: si vous ne remplacez pas la méthode de clonage, le comportement par défaut est une copie superficielle. Si vos objets ne contiennent que des variables membres primitives, tout va bien. Mais dans un langage non typé avec un autre objet comme variable membre, c'est un casse-tête.

  2. sérialisation/désérialisation

$new_object = unserialize(serialize($your_object))

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

92
yogman

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 du clonage:

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

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

$a = clone $b;
9
Leo

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

4
Patricio Rossi

Ce code aide les méthodes de clonage

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
zloctb

Je faisais quelques essais 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
Pyetro

Dans cet exemple, nous allons créer iPhone class et en faire une copie exacte par 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>";
0
Muhammad Ebrahim