Что такое клонирование объектов в php?

Может кто-нибудь объяснить мне

Solutions Collecting From Web of "Что такое клонирование объектов в php?"

Клонирование объектов – это акт создания копии объекта. Как отметил Коди , клонирование на PHP выполняется путем создания мелкой копии объекта. Это означает, что внутренние объекты клонированного объекта не будут клонированы, если вы явно не проинструктируете объект клонировать эти внутренние объекты, определяя магический метод __clone() .

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

Рассмотрим следующие примеры:

 // in this exampe the internal member $_internalObject of both objects // reference the same instance of stdClass in memory. class CloneableClass { private $_internalObject; public function __construct() { // instantiate the internal member $this->_internalObject = new stdClass(); } } $classA = new CloneableClass(); $classB = clone $classA; // in this exampe the internal member $_internalObject of both objects // DON'T reference the same instance of stdClass in memory, but are inividual instances class CloneableClass { private $_internalObject; public function __construct() { // instantiate the internal member $this->_internalObject = new stdClass(); } // on clone, make a deep copy of this object by cloning internal member; public function __clone() { $this->_internalObject = clone $this->_internalObject; } } $classA = new CloneableClass(); $classB = clone $classA; 

Например, случаи клонирования могут быть случаи, когда вы не хотите, чтобы внешние объекты не вмешивались во внутреннее состояние объекта.

Допустим, у вас есть класс User с внутренним адресом Address.

 class Address { private $_street; private $_streetIndex; private $_city; // etc... public function __construct( $street, $streetIndex, $city /* etc.. */ ) { /* assign to internal values */ } } class User { // will hold instance of Address private $_address; public function __construct() { $this->_address = new Address( 'somestreet', '1', 'somecity' /* etc */ ); } public function getAddress() { return clone $this->_address; } } 

Для аргументов, скажем, вы не хотите, чтобы внешние объекты связывались с внутренними объектами Address of User, но вы хотите, чтобы они могли предоставить им копию объекта Address. Приведенный выше пример иллюстрирует это. Метод getAddress возвращает клон объекта адреса вызывающим объектам. Это означает, что если вызывающий объект изменяет объект Address, внутренний адрес пользователя не изменится. Если вы не дали клон, то внешний объект мог бы изменить внутренний адрес пользователя, потому что ссылка указана по умолчанию, а не клоном.

Надеюсь, это все имеет смысл.

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

Клонирование используется для создания подлинной копии объекта. Присвоение объекта другой переменной не создает копию – скорее, она создает ссылку на ту же ячейку памяти, что и объект:

 <?php $o= new stdclass; $o->a= 'b'; $o->b= 'c'; $o2= $o; $o2->a= 'd'; var_dump($o); var_dump($o2); $o3= clone $o; $o3->a= 'e'; var_dump($o); var_dump($o3); ?> 

В этом примере кода выводится следующее:

 object(stdClass)#1 (2) { ["a"]=> string(1) "d" ["b"]=> string(1) "c" } object(stdClass)#1 (2) { ["a"]=> string(1) "d" ["b"]=> string(1) "c" } object(stdClass)#1 (2) { ["a"]=> string(1) "d" ["b"]=> string(1) "c" } object(stdClass)#2 (2) { ["a"]=> string(1) "e" ["b"]=> string(1) "c" } 

Клонирование объектов с точки зрения PHP 5 – это то, что известно как «мелкая копия» . Затем он вызывает метод __clone () для клонируемого объекта.

Если вам нужен глубокий клон – то есть клоны дочерних объектов и клоны объектов внука – вы можете либо перезаписать __clone в каждом из классов, либо просто сериализовать + несериализировать объект:

 function deepClone($object) { return unserialize(serialize($object)); } 

Как поясняется в других ответах, clone делает мелкую копию объекта.

Если вам нужно сделать глубокую копию (то есть рекурсивную копию), вы можете перегрузить методы __clone() .

Вы также можете использовать эту библиотеку: MyCLabs \ DeepCopy , которая более простая и мощная, чем простой клон.