Menu
Coddy logo textTech

__clone & Clonage d'objets

Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy — leçon 48 sur 91.

Lorsque vous affectez un objet à une autre variable en PHP, vous ne créez pas de copie - les deux variables pointent vers le même objet. Pour créer une copie réelle et indépendante, vous devez utiliser le mot-clé clone :

<?php
class Product {
    public function __construct(
        public string $name,
        public float $price
    ) {}
}

$original = new Product("Laptop", 999.99);
$copy = clone $original;

$copy->price = 899.99;
echo $original->price . " - " . $copy->price;

Sortie :

999.99 - 899.99

Par défaut, PHP effectue une copie superficielle - il copie directement toutes les valeurs des propriétés. Cela fonctionne bien pour les valeurs scalaires, mais les objets à l'intérieur de votre objet font toujours référence à la même instance. La méthode magique __clone() vous permet de personnaliser ce comportement :

<?php
class Order {
    public function __construct(
        public int $id,
        public array $items = []
    ) {}
    
    public function __clone(): void {
        $this->id = 0;
        $this->items = [];
    }
}

$order1 = new Order(101, ["Book", "Pen"]);
$order2 = clone $order1;

echo "Original: " . $order1->id . ", Clone: " . $order2->id;

Sortie :

Original: 101, Clone: 0

La méthode __clone() est appelée sur le nouvel objet après que la copie superficielle (shallow copy) a été effectuée. C'est ici que vous réinitialisez les IDs, créez de nouvelles copies des objets imbriqués ou effectuez tout nettoyage nécessaire pour que le clone soit véritablement indépendant.

challenge icon

Défi

Facile

Construisons un système de versionnage de documents qui démontre comment le clonage crée des copies indépendantes et comment la méthode magique __clone() vous permet de personnaliser ce qui se passe lorsqu'un objet est cloné.

Vous organiserez votre code sur deux fichiers :

  • Document.php — Créez une classe Document qui représente un document versionné. Utilisez la promotion de constructeur pour définir un $title public (string), un $content public (string), et un $version public (integer, avec une valeur par défaut de 1). Ajoutez une propriété privée $createdAt qui stocke l'horodatage actuel (utilisez date('Y-m-d H:i:s') dans le constructeur). Votre document a besoin de :
    • getCreatedAt() — retourne l'horodatage de création
    • __clone() — lorsqu'un document est cloné, la version doit être incrémentée de 1, et le $createdAt doit être réinitialisé à l'horodatage actuel (le clone est une nouvelle version créée "maintenant")
  • main.php — Incluez le fichier Document. Vous recevrez trois entrées : un titre, un contenu, et une nouvelle chaîne de contenu pour la version clonée. Créez un Document avec le titre et le contenu. Ensuite, clonez-le pour créer une nouvelle version, et mettez à jour le contenu du clone avec la nouvelle chaîne de contenu. Affichez quatre lignes :
    • La version du document original
    • La version du document cloné
    • Le contenu du document original
    • Le contenu du document cloné

Ce système montre comment __clone() vous permet de contrôler ce qui se passe pendant le clonage. Le document original conserve sa version et son heure de création, tandis que le clone devient automatiquement une nouvelle version avec un horodatage frais — parfait pour suivre l'historique des documents où chaque clone représente une nouvelle révision.

Aide-mémoire

Pour créer une copie indépendante d'un objet, utilisez le mot-clé clone :

<?php
class Product {
    public function __construct(
        public string $name,
        public float $price
    ) {}
}

$original = new Product("Laptop", 999.99);
$copy = clone $original;

$copy->price = 899.99;
echo $original->price . " - " . $copy->price;
// Sortie : 999.99 - 899.99

Par défaut, PHP effectue une copie superficielle de toutes les valeurs de propriété. Pour personnaliser le comportement de clonage, utilisez la méthode magique __clone() :

<?php
class Order {
    public function __construct(
        public int $id,
        public array $items = []
    ) {}
    
    public function __clone(): void {
        $this->id = 0;
        $this->items = [];
    }
}

$order1 = new Order(101, ["Book", "Pen"]);
$order2 = clone $order1;

echo "Original: " . $order1->id . ", Clone: " . $order2->id;
// Sortie : Original: 101, Clone: 0

La méthode __clone() est appelée sur le nouvel objet après la création de la copie superficielle, vous permettant de réinitialiser des propriétés ou de créer des copies indépendantes d'objets imbriqués.

Essayez vous-même

<?php

require_once 'Document.php';

// Lire les entrées
$title = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
$newContent = trim(fgets(STDIN));

// TODO: Créer un Document avec le titre et le contenu

// TODO: Cloner le document pour créer une nouvelle version

// TODO: Mettre à jour le contenu du clone avec la nouvelle chaîne de contenu

// TODO: Afficher quatre lignes :
// 1. La version du document original
// 2. La version du document cloné
// 3. Le contenu du document original
// 4. Le contenu du document cloné

?>
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet