Pregunta

Parece que en PHP los objetos se pasan por referencia. Incluso los operadores de asignación no parecen estar creando una copia del objeto.

Aquí hay una prueba simple y artificial:

<?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'

?>

En ambos casos de impresión obtengo 'after'

Entonces, ¿cómo paso $ a a set_b() por valor, no por referencia?

¿Fue útil?

Solución

En PHP 5+ los objetos se pasan por referencia. En PHP 4 se pasan por valor (es por eso que tenía tiempo de ejecución por referencia, que quedó obsoleto).

Puede usar el operador 'clonar' en PHP5 para copiar objetos:

$objectB = clone $objectA;

Además, son solo objetos que se pasan por referencia, no todo como has dicho en tu pregunta ...

Otros consejos

Las respuestas se encuentran comúnmente en los libros de Java.

  1. clonación: Si no anula el método de clonación, el comportamiento predeterminado es una copia superficial. Si sus objetos solo tienen variables miembro primitivas, está totalmente bien. Pero en un lenguaje sin tipo con otro objeto como variables miembro, es un dolor de cabeza.

  2. serialization/deserialization

$ new_object = unserialize (serialize ($ your_object))

Esto logra una copia profunda con un alto costo dependiendo de la complejidad del objeto.

Según el comentario anterior, si tiene otro objeto como variable miembro, haga lo siguiente:

class MyClass {
  private $someObject;

  public function __construct() {
    $this->someObject = new SomeClass();
  }

  public function __clone() {
    $this->someObject = clone $this->someObject;
  }

}

Ahora puedes hacer clonación:

$bar = new MyClass();
$foo = clone $bar;

Según los documentos ( http://ca3.php.net/language.oop5. clonación ):

$a = clone $b;

Solo para aclarar que PHP usa copy on write, básicamente todo es una referencia hasta que lo modifiques, pero para los objetos necesitas usar clone y el método mágico __clone () como en la respuesta aceptada.

Este código ayuda a clonar métodos

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());

Estaba haciendo algunas pruebas y obtuve esto:     

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" }

?>

En este ejemplo crearemos la clase iPhone y haremos una copia exacta de ella clonando

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>";

Si desea copiar completamente las propiedades de un objeto en una instancia diferente, puede utilizar esta técnica:

Serialízalo a JSON y luego desconéctalo de nuevo a Object.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top