Почему ключевое слово «клон» в PHP не работает должным образом? Внутренние массивы

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

class I {
public $name;
public $value;

public function __construct( $name, $value )
{
$this->name = $name;
$this->value = $value;
}
}

class D {
public $name;
public $items;
public function __construct( $name )
{
$this->name = $name;
$this->items = array(
'I1' => new I( "I1", 1232 ),
'I2' => new I( "I2", 12 ),
'I3' => new I( "I3", "hello" )
);
}

public function addItem( Item $item )
{
array_push( $this->items, $item );
}
}

class B {
public $values;
public function __construct()
{
$this->values = array(
"D1" => new D("D1"),
"D2" => new D("D2"),
"D3" => new D("D3"));
}
}

class A {
public $name;
public $bobject;
public $finals;
public function __construct()
{
$this->bobject = new B();
$this->finals = array();
}
public function addFinal( $name )
{
$final = clone $this->bobject->values[$name];
array_push( $this->finals, $final );
}
}

class C extends A {

}


$c = new C();
$c->addFinal( "D1" );
$c->addFinal( "D1" );
$c->addFinal( "D1" );
$c->addFinal( "D1" );
$c->addFinal( "D2" );
$c->addFinal( "D3" );
$c->addFinal( "D1" );

$c->finals[0]->name = "HelloWorld";
$c->finals[0]->items["I1"]->name="ONLY_MODIFY_THIS";

print_r( $c );
exit;

Если вы выполните его, вы получите это:

genial\C Object
(
[name] =>
[bobject] => genial\B Object
(
[values] => Array
(
[D1] => genial\D Object
(
[name] => D1
[items] => Array
(
[I1] => genial\I Object
(
[name] => ONLY_MODIFY_THIS
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

[D2] => genial\D Object
(
[name] => D2
[items] => Array
(
[I1] => genial\I Object
(
[name] => I1
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

[D3] => genial\D Object
(
[name] => D3
[items] => Array
(
[I1] => genial\I Object
(
[name] => I1
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

)

)

[finals] => Array
(
[0] => genial\D Object
(
[name] => HelloWorld
[items] => Array
(
[I1] => genial\I Object
(
[name] => ONLY_MODIFY_THIS
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

[1] => genial\D Object
(
[name] => D1
[items] => Array
(
[I1] => genial\I Object
(
[name] => ONLY_MODIFY_THIS
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

[2] => genial\D Object
(
[name] => D1
[items] => Array
(
[I1] => genial\I Object
(
[name] => ONLY_MODIFY_THIS
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

[3] => genial\D Object
(
[name] => D1
[items] => Array
(
[I1] => genial\I Object
(
[name] => ONLY_MODIFY_THIS
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

[4] => genial\D Object
(
[name] => D2
[items] => Array
(
[I1] => genial\I Object
(
[name] => I1
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

[5] => genial\D Object
(
[name] => D3
[items] => Array
(
[I1] => genial\I Object
(
[name] => I1
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

[6] => genial\D Object
(
[name] => D1
[items] => Array
(
[I1] => genial\I Object
(
[name] => ONLY_MODIFY_THIS
[value] => 1232
)

[I2] => genial\I Object
(
[name] => I2
[value] => 12
)

[I3] => genial\I Object
(
[name] => I3
[value] => hello
)

)

)

)

)

Модификация «ONLY_MODIFY_THIS» затрагивает несколько объектов, когда предполагается, что они влияют только на первый.

Я хочу две вещи:

  1. Сохранить оригинальные объекты D1, D2 и D3

  2. Измените только объект, проиндексированный в массиве финалов.

0

Решение

Из документов [1]:

| Когда объект клонируется, PHP 5 выполнит поверхностную копию
| все свойства объекта.

Это то же самое для PHP 7 (исправит эту незначительную проблему сразу).
Вы ищете глубокую копию.

[1] http://php.net/manual/en/language.oop5.cloning.php

0

Другие решения

Других решений пока нет …