Domanda

Sembra che in PHP gli oggetti vengano passati per riferimento. Persino gli operatori di assegnazione non sembrano creare una copia dell'oggetto.

Ecco una semplice prova inventata:

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

?>

In entrambi i casi di stampa ricevo 'dopo'

Quindi, come passo $ a a set_b() per valore, non per riferimento?

È stato utile?

Soluzione

In PHP 5+ gli oggetti vengono passati per riferimento. In PHP 4 vengono passati in base al valore (ecco perché ha avuto un tempo di esecuzione per riferimento, che è diventato obsoleto).

Puoi usare l'operatore 'clone' in PHP5 per copiare oggetti:

$objectB = clone $objectA;

Inoltre, sono solo gli oggetti che vengono passati per riferimento, non tutto come hai detto nella tua domanda ...

Altri suggerimenti

Le risposte si trovano comunemente nei libri di Java.

  1. clonazione: Se non si ignora il metodo clone, il comportamento predefinito è copia superficiale. Se i tuoi oggetti hanno solo variabili membro primitive, è del tutto ok. Ma in un linguaggio non tipizzato con un altro oggetto come variabili membro, è un mal di testa.

  2. serializzazione / deserializzazione

$ new_object = unserialize (serialize ($ your_object))

Ciò consente di ottenere copie profonde con un costo elevato a seconda della complessità dell'oggetto.

Secondo il commento precedente, se si dispone di un altro oggetto come variabile membro, procedere come segue:

class MyClass {
  private $someObject;

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

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

}

Ora puoi fare la clonazione:

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

Secondo i documenti ( http://ca3.php.net/language.oop5. clonazione ):

$a = clone $b;

Solo per chiarire PHP usa copia su scrittura, quindi praticamente tutto è un riferimento fino a quando non lo modifichi, ma per gli oggetti devi usare clone e il metodo magico __clone () come nella risposta accettata.

Questo codice aiuta a clonare metodi

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

Stavo facendo dei test e ho ottenuto questo:     

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

?>

In questo esempio creeremo la classe iPhone e ne faremo una copia esatta 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>";

Se si desidera copiare completamente le proprietà di un oggetto in un'istanza diversa, è possibile utilizzare questa tecnica:

Serializzalo su JSON e poi ridenializza nuovamente in Object.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top