Criar uma cópia de um objeto com propriedades totalmente replicadas nem sempre é o comportamento desejado. Um bom exemplo da necessidade para construtores de cópia é se você tem um objeto que representa uma janela do GTK e um objeto guarda o resource dessa janela. Quando você criar uma duplicata, você pode querer criar uma nova janela com as mesmas propriedades e fazer o novo objeto quarda o resource da nova janela. Outro exemplo é se seu objeto guarda uma referência a outro objeto o qual ele usa e quando você replicar o objeto pai, você quer que seja criada uma nova instância desse outro objeto para que a réplica tenha sua própria cópia separada.
Uma cópia de objeto é criada usando a palavra-chave 'clone' (que chama o método __clone() do objeto, se possível). O método __clone() de um objeto não pode ser chamado diretamente.
$copia_do_objeto = clone $objeto;
Quando um objeto é clonado, PHP 5 fará uma cópia superficial de todas as propriedades do objeto. Qualquer propriedade que seja referência a outra variável, permanecerá referência. Se um método __clone() for definido, então este será chamado, permitindo definir qualquer alteração necessária nas propriedades.
Exemplo #1 Clonando um objeto
<?php
class SubObjeto {
static $instancias = 0;
public $instancia;
public function __construct() {
$this->$instancia = ++self::$instancias;
}
public function __clone() {
$this->$instancia = ++self::$instancias;
}
}
class MeuClonavel {
public $objeto1;
public $objeto2;
function __clone() {
// Força uma cópia de this->objeto, ou então
// apontará para o mesmo objeto
$this->objeto1 = clone $this->objeto1;
}
}
$obj = new MeuClonavel();
$obj->objeto1 = new SubObjeto();
$obj->objeto2 = new SubObjeto();
$obj2 = clone $obj;
print("Objeto Original:\n");
print_r($obj);
print("Objeto Clonado:\n");
print_r($obj2);
?>
O exemplo acima irá imprimir:
Objeto Original: MeuClonavel Object ( [objeto1] => SubObjeto Object ( [instancia] => 1 ) [objeto2] => SubObjeto Object ( [instancia] => 2 ) ) Objeto Clonado: MeuClonavel Object ( [objeto1] => SubObjeto Object ( [instancia] => 3 ) [objeto2] => SubObjeto Object ( [instancia] => 2 ) )