Why keyword 'clone' in PHP not working as expected? Internal arrays

时间:2018-12-03 13:15:32

标签: php class copy clone copy-constructor

I have a method in a class that copy an object from an array and put it into another, I use clone to avoid the possibility to modify the original object. This is the code:

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;

If you execute it you will get this:

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
                                )

                        )

                )

        )

)

The modification "ONLY_MODIFY_THIS" affects several objects, when is supposed to affect only the first.

I want two things:

  1. Preserve original objects D1, D2 and D3

  2. Modify only the object indexed in the finals array.

1 个答案:

答案 0 :(得分:0)

从文档[1]:

|克隆对象后,PHP 5将执行以下操作的浅表副本: |对象的所有属性。

这与PHP 7相同(将立即解决此小问题)。 您正在寻找深层副本。

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