代码之家  ›  专栏  ›  技术社区  ›  Nick Stinemates

如何在PHP中创建对象的副本?

  •  136
  • Nick Stinemates  · 技术社区  · 16 年前

    在PHP中,对象似乎是通过引用传递的。即使是赋值操作符也不会创建对象的副本。

    下面是一个简单的、人为的证据:

    <?php
    
    class A {
        public $b;
    }
    
    
    function set_b($obj) { $obj->b = "after"; }
    
    $a = new A();
    $a->b = "before";
    $c = $a; //i would especially expect this to create a copy.
    
    set_b($a);
    
    print $a->b; //i would expect this to show 'before'
    print $c->b; //i would ESPECIALLY expect this to show 'before'
    
    ?>
    

    在这两个印刷品案例中,我都在“追寻”

    那么,我怎么通过 $A SETIB() 按价值,而不是参照?

    9 回复  |  直到 7 年前
        1
  •  238
  •   Eran Galperin    16 年前

    在php 5+中,对象是通过引用传递的。在php 4中,它们是按值传递的(这就是为什么它有运行时按引用传递的原因,这已被弃用)。

    可以使用php5中的“clone”运算符复制对象:

    $objectB = clone $objectA;
    

    而且,它只是通过引用传递的对象,而不是您在问题中所说的所有内容…

        2
  •  83
  •   kamal pal    9 年前

    答案通常在Java书籍中找到。

    1. 克隆: 如果不重写Clone方法,则默认行为为Shallow Copy。如果您的对象只有基本成员变量,那么完全可以。但在另一个对象作为成员变量的无类型语言中,这是一个头痛的问题。

    2. 序列化/反序列化

    $new_object = unserialize(serialize($your_object))

    根据对象的复杂性,这将以很高的成本实现深度复制。

        3
  •  18
  •   John Carter    15 年前

    根据前面的注释,如果您将另一个对象作为成员变量,请执行以下操作:

    class MyClass {
      private $someObject;
    
      public function __construct() {
        $this->someObject = new SomeClass();
      }
    
      public function __clone() {
        $this->someObject = clone $this->someObject;
      }
    
    }
    

    现在可以克隆:

    $bar = new MyClass();
    $foo = clone $bar;
    
        4
  •  9
  •   rink.attendant.6    11 年前

    根据文件( http://ca3.php.net/language.oop5.cloning ):

    $a = clone $b;
    
        5
  •  4
  •   Patricio Rossi    9 年前

    为了说明php使用的是copy-on-write,所以在您修改它之前,基本上所有东西都是一个引用,但是对于对象,您需要使用clone和接受答案中的uclone()magic方法。

        6
  •  1
  •   zloctb    11 年前

    此代码帮助克隆方法

    class Foo{
    
        private $run=10;
        public $foo=array(2,array(2,8));
        public function hoo(){return 5;}
    
    
        public function __clone(){
    
            $this->boo=function(){$this->hoo();};
    
        }
    }
    $obj=new Foo;
    
    $news=  clone $obj;
    var_dump($news->hoo());
    
        7
  •  1
  •   Pyetro    10 年前

    我做了一些测试,得到了:

    class A {
      public $property;
    }
    
    function set_property($obj) {
      $obj->property = "after";
      var_dump($obj);
    }
    
    $a = new A();
    $a->property = "before";
    
    // Creates a new Object from $a. Like "new A();"
    $b = new $a;
    // Makes a Copy of var $a, not referenced.
    $c = clone $a;
    
    set_property($a);
    // object(A)#1 (1) { ["property"]=> string(5) "after" }
    
    var_dump($a); // Because function set_property get by reference
    // object(A)#1 (1) { ["property"]=> string(5) "after" }
    var_dump($b);
    // object(A)#2 (1) { ["property"]=> NULL }
    var_dump($c);
    // object(A)#3 (1) { ["property"]=> string(6) "before" }
    
    // Now creates a new obj A and passes to the function by clone (will copied)
    $d = new A();
    $d->property = "before";
    
    set_property(clone $d); // A new variable was created from $d, and not made a reference
    // object(A)#5 (1) { ["property"]=> string(5) "after" }
    
    var_dump($d);
    // object(A)#4 (1) { ["property"]=> string(6) "before" }
    
    ?>
    
        8
  •  0
  •   Muhammad Ebrahim    7 年前

    在这个例子中,我们将创建 苹果手机 课上,并由 克隆

    class iPhone {
    
    public $name;
    public $email;
    
        public function __construct($n, $e) {
    
           $this->name = $n;
           $this->email = $e;
    
        }
    }
    
    
    $main = new iPhone('Dark', 'm@m.com');
    $copy = clone $main;
    
    
    // if you want to print both objects, just write this    
    
    echo "<pre>"; print_r($main);  echo "</pre>";
    echo "<pre>"; print_r($copy);  echo "</pre>";
    
        9
  •  -1
  •   Flexo - Save the data dump sunny moon    8 年前

    如果要完全复制其他实例中对象的属性,则可能需要使用此技术:

    将其序列化为JSON,然后将其反序列化回对象。