Клонирование объектов

Создание копии объекта с абсолютно идентичными свойствами не всегда является приемлемым вариантом. Хорошим примером необходимости копирования конструкторов может послужить ситуация, когда у вас есть объект, представляющий собой окно GTK и содержащий ресурс-идентификатор этого окна; когда вы создаете копию этого объекта, вам может понадобиться, чтобы копия объекта содержала ресурс-идентификатор нового окна. Другим примером может послужить ситуация, когда ваш объект содержит ссылку на какой-либо другой используемый объект и, когда вы создаёте копию родительского объекта, вам нужно также создать новый экземпляр этого другого объекта, так, чтобы копия объекта-контейнера содержала собственный отдельный экземпляр содержащегося объекта.

Копия объекта создается с использованием ключевого слова clone (который вызывает метод __clone() объекта, если это возможно). Вызов метода __clone() не может быть осуществлён напрямую.

$copy_of_object = clone $object;

При клонировании объекта, PHP выполняет неполную копию всех свойств объекта. Любые свойства, являющиеся ссылками на другие переменные, останутся ссылками.

__clone ( ) : void

После завершения клонирования, если метод __clone() определен, тогда будет вызываться метод __clone() вновь созданного объекта, для возможного изменения всех необходимых свойств.

Пример #1 Клонирование объекта

<?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()
    {
        
// Принудительно копируем this->object, иначе
        // он будет указывать на один и тот же объект.
        
$this->object1 = clone $this->object1;
    }
}

$obj = new MyCloneable();

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

$obj2 = clone $obj;


print(
"Оригинальный объект:\n");
print_r($obj);

print(
"Клонированный объект:\n");
print_r($obj2);

?>

Результат выполнения данного примера:

Оригинальный объект:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 1
        )

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

)
Клонированный объект:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 3
        )

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

)

В PHP 7.0.0 введена возможность обращения к свойствам/методам только что склонированного объекта:

Пример #2 Доступ к только что склонированному объекту

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

Результатом выполнения данного примера будет что-то подобное:

2016