Menu
Coddy logo textTech

__clone e Clonagem de Objetos

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy — lição 48 de 91.

Quando você atribui um objeto a outra variável no PHP, você não cria uma cópia - ambas as variáveis apontam para o mesmo objeto. Para criar uma cópia independente real, você precisa usar a palavra-chave 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;

Saída:

999.99 - 899.99

Por padrão, o PHP realiza uma cópia rasa (shallow copy) - ele copia todos os valores das propriedades diretamente. Isso funciona bem para valores escalares, mas objetos dentro do seu objeto ainda referenciam a mesma instância. O método mágico __clone() permite que você personalize este comportamento:

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

Saída:

Original: 101, Clone: 0

O método __clone() é chamado no novo objeto após a cópia rasa (shallow copy) ser feita. É aqui que você redefine IDs, cria novas cópias de objetos aninhados ou realiza qualquer limpeza necessária para que o clone seja verdadeiramente independente.

challenge icon

Desafio

Fácil

Vamos construir um sistema de versionamento de documentos que demonstra como a clonagem cria cópias independentes e como o método mágico __clone() permite que você personalize o que acontece quando um objeto é clonado.

Você organizará seu código em dois arquivos:

  • Document.php — Crie uma classe Document que representa um documento versionado. Use a promoção de construtor para definir um $title público (string), um $content público (string) e um $version público (inteiro, com valor padrão 1). Adicione uma propriedade privada $createdAt que armazena o timestamp atual (use date('Y-m-d H:i:s') no construtor). Seu documento precisa de:
    • getCreatedAt() — retorna o timestamp de criação
    • __clone() — quando um documento é clonado, a versão deve ser incrementada em 1, e o $createdAt deve ser redefinido para o timestamp atual (o clone é uma nova versão criada "agora")
  • main.php — Inclua o arquivo Document. Você receberá três entradas: um título, um conteúdo e uma nova string de conteúdo para a versão clonada. Crie um Document com o título e o conteúdo. Em seguida, clone-o para criar uma nova versão e atualize o conteúdo do clone para a nova string de conteúdo. Imprima quatro linhas:
    • A versão do documento original
    • A versão do documento clonado
    • O conteúdo do documento original
    • O conteúdo do documento clonado

Este sistema mostra como o __clone() permite que você controle o que acontece durante a clonagem. O documento original mantém sua versão e hora de criação, enquanto o clone torna-se automaticamente uma nova versão com um novo timestamp — perfeito para rastrear o histórico de documentos onde cada clone representa uma nova revisão.

Folha de consulta

Para criar uma cópia independente de um objeto, use a palavra-chave 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;
// Saída: 999.99 - 899.99

Por padrão, o PHP realiza uma shallow copy (cópia rasa) de todos os valores das propriedades. Para personalizar o comportamento de clonagem, use o método mágico __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;
// Saída: Original: 101, Clone: 0

O método __clone() é chamado no novo objeto após a cópia rasa ser feita, permitindo que você redefina propriedades ou crie cópias independentes de objetos aninhados.

Experimente você mesmo

<?php

require_once 'Document.php';

// Ler entradas
$title = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
$newContent = trim(fgets(STDIN));

// TODO: Criar um Document com o título e o conteúdo

// TODO: Clonar o documento para criar uma nova versão

// TODO: Atualizar o conteúdo do clone para a nova string de conteúdo

// TODO: Imprimir quatro linhas:
// 1. A versão do documento original
// 2. A versão do documento clonado
// 3. O conteúdo do documento original
// 4. O conteúdo do documento clonado

?>
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos