Полный цикл в digital

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

При присваивании объекта класса другой переменной создается новая ссылка на тот же объект:

<?
class Person
{
    public $name;
    function __construct($name)
    {
        $this->name = $name;
    }
}
$tom = new Person("Tom");
$bob = $tom;
$bob->name = "Bob";
// Bob
echo $tom->name; 

В данном случае после присваивания $bob = $tom; обе переменных будут указывать на один и тот же объект. Поэтому если мы поменяем свойство $name у одной переменной, то это измение затронет и другую переменую. Так как они ссылаются на один и тот же объект.

Однако такое поведение может быть нежелательным, если мы хотим, чтобы после копирования переменные представляли независимые друг от друга объекты. И для этого PHP предоставляет оператор clone:

<?
class Person
{
    public $name;
    function __construct($name)
    {
        $this->name = $name;
    }
}
$tom = new Person("Tom");
// копируем объект из $tom в переменную $bob
$bob = clone $tom; 
$bob->name = "Bob";
// Tom
echo $tom->name;

При применении оператора clone все свойства, которые представляют примитивные типы и массивы, копируются в новый объект. Однако, что если у нас свойство класса представляет другой класс:

<?
class Company
{
    public $name;
    function __construct($name)
    {
        $this->name = $name;
    }
}
class Person
{
    public $name, $company;
    function __construct($name, $company)
    {
        $this->name = $name;
        $this->company = $company;
    }
}
$microsoft = new Company("Microsoft");
$tom = new Person("Tom", $microsoft);
// копируем объект из $tom в переменную $bob
$bob = clone $tom; 
$bob->name = "Bob";
// изменяем у Боба название компании
$bob->company->name = "Google"; 
$bob->languages[0] = "french";
// Google - у Тома тоже изменилась компания
echo $tom->company->name;

Здесь в принципе мы сталкиваемся с той же ситуацией, что и в первом примере. Класс Person содержит свойство, которое представляет класс Company. При клонировании объекта:

$bob = clone $tom;

Обе переменных $tom и $bob будут содержать ссылку на один и тот же объект Company. Соответственно если через одну переменную изменить свойства этого объекта:

$bob->company->name = "Google";

то изменение затронет и другую переменную:

echo $tom->company->name; // Google

Чтобы выйти из этой ситуации, необходимо в классе определить метод __clone. Он вызывается при клонировании и может применяться для клонирования вложенных объектов:

<?
class Company
{
    public $name;
    function __construct($name)
    {
        $this->name = $name;
    }
}
class Person
{
    public $name, $company;
    function __construct($name, $company)
    {
        $this->name = $name;
        $this->company = $company;
    }
    function __clone()
    {
        $this->company = clone $this->company;
    }
}
$microsoft = new Company("Microsoft");
$tom = new Person("Tom", $microsoft);
// копируем объект из $tom в переменную $bob
$bob = clone $tom; 
$bob->name = "Bob";
// изменяем у Боба название компании
$bob->company->name = "Google"; 
$bob->languages[0] = "french";
// Microsoft - у Тома НЕ изменилась компания
echo $tom->company->name;
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг