Clonage d'objets

Le fait de créer une copie d'un objet possédant exactement les mêmes propriétés n'est pas toujours le comportement que l'on souhaite. Un bon exemple pour illustrer le besoin d'un constructeur de copie : dans le cas d'un objet qui représente une fenêtre GTK et qui contient la ressource représentant cette fenêtre GTK, lors de la création d'une copie, il peut être souhaitable de créer une nouvelle fenêtre avec les mêmes propriétés, mais que le nouvel objet contienne une ressource représentant la nouvelle fenêtre. Un autre exemple est le cas où un objet contient une référence vers un autre objet qu'il utilise et, lors de la réplication de l'objet parent, il est souhaitable de créer une nouvelle instance de cet autre objet afin que la réplique possède sa propre copie séparée.

Une copie d'objet est créée en utilisant le mot-clé clone (qui fait appel à la méthode __clone() de l'objet, si possible).

$copy_of_object = clone $object;

Lorsqu'un objet est cloné, PHP effectue une copie superficielle de toutes les propriétés de l'objet. Toutes les propriétés qui sont des références à d'autres variables demeureront des références.

__clone(): void

Une fois le clonage effectué, si une méthode __clone() est définie, la méthode __clone() du nouvel objet sera appelée, pour permettre à chaque propriété qui doit l'être d'être modifiée.

Exemple #1 Exemple de duplication d'objets

<?php
class SubObject
{
static
$instances = 0;
public
$instance;

public function
__construct() {
$this->instance = ++self::$instances;
}

public function
__clone() {
$this->instance = ++self::$instances;
}
}

class
MyCloneable
{
public
$object1;
public
$object2;

function
__clone()
{
// Force la copie de this->object, sinon
// il pointera vers le même objet.
$this->object1 = clone $this->object1;
}
}

$obj = new MyCloneable();

$obj->object1 = new SubObject();
$obj->object2 = new SubObject();

$obj2 = clone $obj;


print
"Objet original :\n";
print_r($obj);

print
"Objet cloné :\n";
print_r($obj2);

?>

L'exemple ci-dessus va afficher :

Objet original :
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 1
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )

)
Objet cloné :
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 3
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )

)

Il est possible d'accéder à un membre d'un objet fraîchement cloné dans une seule expression:

Exemple #2 Accès à un membre d'un objet fraîchement cloné

<?php
$dateTime
= new DateTime();
echo (clone
$dateTime)->format('Y');
?>

Résultat de l'exemple ci-dessus est similaire à :

2016