Иногда может потребоваться создать копию уже заполненного объекта, чтобы не устанавливать свойства заново. Для этого в PHP используется ключевое слово clone. Например, предположим ситуацию, что мы создали объект класса и заполнили часть его свойств:
<?php
class User {
public $name;
private $city;
public function __construct($name)
{
$this->name = $name;
}
public function setCity($value)
{
$this->city = $value;
}
}
$user = new User("Иван");
$user->setCity("Москва");
Рассмотрим следующие примеры клонирования объектов.
Удачный пример клонирования объекта
Предположим, что у Ивана есть сестра Маша, которая живет в том же городе. Чтобы не создавать объект заново, мы можем сделать копию уже существующего объекта и поменять только имя:
<?php
$user = new User("Иван");
$user->setCity("Москва");
$user2 = clone $user;
$user2->name = "Маша";
print_r($user);
print_r($user2);
В данном случае мы описали пример удачного клонирования объектов, поскольку в переменной $user2 у нас будет копия объекта $user, а не ссылка на него.
Неудачный пример клонирования объекта
Если в указанном выше примере убрать ключевое слово clone, то мы получим ссылку на объект $user, а не его копию:
<?php
$user = new User("Иван");
$user->setCity("Москва");
$user2 = $user;
$user2->name = "Маша";
print_r($user);
print_r($user2);
Тем самым, при изменении свойства name у объекта $user2 мы поменяем данное свойство и у объекта $user.
Изменения при клонировании объекта
С помощью магического метода __clone мы можем указать дополнительные действия, которые требуется выполнить при клонировании объекта. Например, мы можем сделать, чтобы при клонировании объекта User, его свойство name было пустой строкой:
<?php
class User {
public $name;
private $city;
public function __construct($name)
{
$this->name = $name;
}
public function setCity($value)
{
$this->city = $value;
}
public function __clone()
{
$this->name = "";
}
}
$user = new User("Иван");
$user->setCity("Москва");
$user2 = clone $user;
print_r($user);
print_r($user2);
Таким образом в переменной $user2 свойство name будет пустым.
Запрещаем клонирование
Чтобы запретить клонирование объектов класса, нам требуется сделать приватным магический метод __clone, таким образом пример ниже выдаст фатальную ошибку:
<?php
class User {
public $name;
private $city;
public function __construct($name)
{
$this->name = $name;
}
public function setCity($value)
{
$this->city = $value;
}
private function __clone()
{
}
}
$user = new User("Иван");
$user->setCity("Москва");
$user2 = clone $user; // здесь будет ошибка