__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 em PHP, não cria uma cópia — ambas as variáveis apontam para o mesmo objeto. Para criar uma cópia independente de fato, 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.99Por padrão, o PHP realiza uma cópia superficial — ele copia diretamente todos os valores das propriedades. Isso funciona bem para valores escalares, mas os objetos dentro do seu objeto ainda fazem referência à mesma instância. O método mágico __clone() permite personalizar esse 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: 0O método __clone() é chamado no novo objeto após a criação da cópia superficial. É nesse ponto que você redefine os IDs, cria novas cópias de objetos aninhados ou realiza qualquer limpeza necessária para que o clone seja verdadeiramente independente.
Desafio
FácilVamos criar um sistema de versionamento de documentos que demonstra como a clonagem cria cópias independentes e como o método mágico __clone() permite personalizar o que acontece quando um objeto é clonado.
Você organizará seu código em dois arquivos:
Document.php: crie uma classeDocumentque represente um documento versionado. Use a promoção de construtor para definir um$titlepúblico (string), um$contentpúblico (string) e um$versionpúblico (inteiro, com valor padrão 1). Adicione uma propriedade$createdAtprivada que armazene o timestamp atual (usedate('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$createdAtdeve 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 umDocumentcom o título e o conteúdo. Em seguida, clone-o para criar uma nova versão e atualize o conteúdo do clone com 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 __clone() permite controlar o que acontece durante a clonagem. O documento original mantém sua versão e seu horário de criação, enquanto o clone se torna automaticamente uma nova versão com um timestamp atualizado, perfeito para acompanhar o histórico do documento, em que cada clone representa uma nova revisão.
Experimente você mesmo
<?php
require_once 'Document.php';
// Ler entradas
$title = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
$newContent = trim(fgets(STDIN));
// TODO: Crie um Document com o título e o conteúdo
// TODO: Clone o documento para criar uma nova versão
// TODO: Atualize o conteúdo do clone para a nova string de conteúdo
// TODO: Imprima 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
?>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
1Fundamentos de OOP
Arquivos externosIntrodução à OOPClasses vs. objetosA palavra-chave $thisMétodosPropriedadesConstrutor (__construct)Destrutor (__destruct)Recapitulação - Calculadora simples4Herança
Herança BásicaA Palavra-chave parent::Sobrescrita de MétodosA Palavra-chave finalClasses AbstratasRecapitulação - Hierarquia de Funcionários7Encapsulamento
Público, Protegido, PrivadoModificadores de Acesso em ProfundidadeGetters e SettersOcultação de InformaçõesPromoção de Construtor (8.0)Recapitulação - Sistema de Registros de Alunos10Conceitos Avançados de OOP
Composição vs. HerançaInjeção de DependênciaClasses AnônimasEnums (PHP 8.1)Fibras (PHP 8.1)Análise Profunda da Clonagem de ObjetosGeradores e Iteradores13Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Repository2Namespaces e Autoloading
Introdução a NamespacesA palavra-chave usePadrão de Autoloading PSR-4Autoloader do ComposerRecapitulação - Projeto organizado5Interfaces e Contratos
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesInterface vs Classe AbstrataTipagem com InterfacesRecapitulação - Calculadora de Formas8Métodos Mágicos
Introdução aos Métodos Mágicos__toString e __debugInfo__get, __set, __isset, __unset__call e __callStatic__clone e Clonagem de Objetos__serialize e __unserializeRecapitulação - Coleção Personalizada11Sistema de Tipos e Tratamento de Erros
Declarações de TiposTipos NulosTipos de União e InterseçãoClasses de ExceçãoHierarquia de Exceções PersonalizadaTry, Catch, FinallyRecapitulação - Validador de Formulário14Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses de Livros e Usuários3Propriedades de Classes
Propriedades de Instância vs. EstáticasConstantes em ClassesMétodos e Propriedades EstáticosPropriedades Privadas e ProtegidasPropriedades Somente para Leitura (PHP 8.1)Recapitulação - Gerenciador de Contas Bancárias6Polimorfismo
Revisão da Sobrescrita de MétodosPolimorfismo via InterfacesIndicação de Tipos e Tipos UnionVinculação Estática TardiaRecapitulação - Processador de Pagamentos9Traits
Introdução a TraitsUsando Múltiplos TraitsResolução de Conflitos entre TraitsMétodos Abstratos em TraitsTraits vs. Herança12Padrões de Projeto – Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão StrategyPratique por conta própria: Compilador de PHP online