Создание копии объекта с абсолютно идентичными свойствами не всегда является приемлемым вариантом. Хорошим примером необходимости копирования конструкторов может послужить ситуация, когда у вас есть объект, представляющий собой окно GTK и содержащий ресурс-идентификатор этого окна; когда вы создаете копию этого объекта, вам может понадобиться, чтобы копия объекта содержала ресурс-идентификатор нового окна. Другим примером может послужить ситуация, когда ваш объект содержит ссылку на какой-либо другой используемый объект и, когда вы создаёте копию родительского объекта, вам нужно также создать новый экземпляр этого другого объекта, так, чтобы копия объекта-контейнера содержала собственный отдельный экземпляр содержащегося объекта.
Копия объекта создается с использованием ключевого слова clone (который вызывает метод __clone() объекта, если это возможно). Вызов метода __clone() не может быть осуществлён непосредственно.
$copy_of_object = clone $object;
При клонировании объекта, PHP 5 выполняет неполную копию всех свойств объекта. Любые свойства, являющиеся ссылками на другие переменные, останутся ссылками.
По завершении клонирования, если у класса был определен метод __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