web-dev-qa-db-fra.com

Copie d'objet contre clone dans PHP

Considérer ce qui suit:

$object1 = new stdClass();
$object2 = $object1;
$object3 = clone $object1;

$object1->content = 'Ciao';

var_dump($object1);
 // Outputs object(stdClass)#1 (1) { ["content"]=> string(4) "Ciao" }
var_dump($object2);
 // Outputs object(stdClass)#1 (1) { ["content"]=> string(4) "Ciao" }
var_dump($object3);
 // Outputs object(stdClass)#2 (0) { }

Est-ce un comportement normal PHP que $object2 a un contenu identique à $object1?

Pour moi, cela ressemble à $object2 est une référence à $object1 au lieu d'une copie. Le clonage de l'objet avant de modifier le contenu agit comme une copie. Ce comportement est différent de ce qui se passe avec les variables et me semble peu intuitif.

27
ddamasceno

Oui, c'est normal. Les objets sont toujours "assignés" par référence en PHP5. Pour réellement faire une copie d'un objet, vous devez le clone.

Pour être plus correct cependant, permettez-moi de citer le manuel :

Depuis PHP5, une variable objet ne contient plus l'objet lui-même comme valeur. Il contient uniquement un identifiant d'objet qui permet aux accesseurs d'objet de trouver l'objet réel. Lorsqu'un objet est envoyé par argument, retourné ou affecté à une autre variable, les différentes variables ne sont pas des alias: elles contiennent une copie de l'identifiant, qui pointe vers le même objet.

39
deceze

C'est normal et je ne considérerai pas cela comme non intuitif (pour les instances d'objet):

$object1 = new stdClass();

Attribue une nouvelle instance d'objet à $object1.

$object2 = $object1;

Attribue l'instance d'objet à $object2.

$object3 = clone $object1;

Attribue une nouvelle instance d'objet clonée à partir d'une instance d'objet existante à $object3.

Si ce n'était pas le cas, chaque fois que vous devez passer une instance d'objet concret, vous devez la passer par référence. C'est lourd au moins mais PHP l'a fait dans la version 4 (comparer zend.ze1_compatibility_mode core ). Ce n'était pas utile.

Le clonage permet à l'objet de spécifier comment il est copié .

13
hakre

copie d'objet vs clone d'objet

class test{
public $name;
public $addr;
}
// i create a object $ob
$ob=new test();

// object copy 

$ob2=$ob;

// in object copy both object will represent same memory address 
// example 
$ob->name='pankaj raghuwanshi';

// i am printing second object
echo $ob2->name;
// output is : pankaj raghuwanshi

// another example 

$ob2->name='raghuwanshi pankaj';
echo $ob->name;
// output is :  raghuwanshi pankaj

// it means in copy of object original and copy object share same memory place

maintenant clone d'un objet

$ob1=clone $ob;

echo $ob1->name;  // output is :  raghuwanshi pankaj
echo $ob->name;   // output is :  raghuwanshi pankaj

 $ob1->name='PHP Clone';
 $ob->name='PHP Obj';

echo $ob1->name;  // output is :  PHP Clone
echo $ob->name;   // output is :  PHP Obj

// on the base of these output we can say both object have their own memory space 
// both are independent 
9
PankajR

Les objets en php5 sont essentiellement des pointeurs, c'est-à-dire qu'une variable objet ne contient qu'une adresse des données objet situées ailleurs. Une mission $obj1 = $obj2 copie uniquement cette adresse et ne touche pas aux données elles-mêmes. Cela peut en effet sembler contre-intuitif, mais en fait, c'est assez pratique, car vous n'avez que rarement besoin d'avoir deux copies de l'objet. Je souhaite que les tableaux php utilisent la même sémantique.

4
user187291