Kopie oder Referenz?

Bei Variablen

Variablenzuweisung

Eine Variable hat einen Namen, der einem gespeicherten Wert zugeordnet ist. Soweit bekannt aus den PHP-Grundlagen.
Beispiel zuweisung_var.php
<?php
 # zuweisung_var.php

 # Variablenzuweisung
 $a = 69; # Variable $a wird angelegt und mit dem Wert 69 initialisiert
 $b = $a; # Variable $b wird angelegt, Wert aus $a wird kopiert
 print "Nach Initialisierung: $a, $b".PHP_EOL; // 69, 69
 
 $b = 88; # Wir ändern den Wert von $b
 print "Nach Änderung von b: $a, $b".PHP_EOL; // 69, 88

 unset($a,$b);
?>
Beide Variablen sind unabhängig voneinander, jede hat ihren eigenen gespeicherten Wert. $b ist nach der Zuweisung eine Kopie von $a.

Zuweisung per Referenzzeichen

Die Zuweisung per Referenzzeichen ändert die Situation.
Beispiel referenz_var.php
<?php
 # referenz_var.php

 # Variablenzuweisung
 $a = 69;  # Variable $a anlegen und initialisieren mit dem Wert 69
 $b = &$a; # $b wird zur Referenz auf $a
 print "Nach Initialisierung: $a, $b".PHP_EOL; // 69, 69
 
 $b = 88;  # Wir ändern den Wert von $b
 print 'Nach Änderung von $b: '."$a, $b".PHP_EOL; // 88, 88

 unset($a,$b);
?>
$b und $a sind keine unabhängigen Variablen, sondern gleichgestellte Namen auf denselben gespeicherten Wert.

Kopie einer Referenz?

Wir erweitern das Beispiel mit folgendem Code.
 $c = $b;
 print '$c erhält den Wert von $b: '
      ."$a, $b, $c".PHP_EOL; // 88, 88, 88
 $b = 77;
 print 'Nach erneuter Änderung von $b: '
      ."$a, $b, $c".PHP_EOL; // 77, 77, 88

 unset($a,$b,$c);
Analog zu anderen Programmiersprachen könnte man auf den Gedanken kommen, weil im Beispiel $b eine Referenz auf $a ist, dass auch $c eine Referenz auf $a wird. Stimmt in PHP aber nicht.
Eine Referenz in PHP von einer Variablen liefert eben nur einen weiteren Namen zur Variablen, der zu allen anderen Namen der Variablen gleichgestellt ist. Anders formuliert: Jeder Variablenname ist quasi eine Referenz auf seinen Wert.
Egal, ob wir im Beispiel $c = $b; oder $c = $a; schreiben, die Wirkung ist identisch. Wir erhalten in beiden Fällen eine Kopie derselben Variablen.
Das muss man auch beim Löschen von Variablen beachten. Mit unset($a); in unserem Beispiel würden wir nur einen Namen entfernen, nicht den gespeicherten Wert. Die Variable bleibt also erhalten. Erst wenn alle Namen rückgesetzt werden: unset($a,$b); wird der gespeicherte Wert freigegeben und die Variable ist gelöscht.

Bei Objekten

Eine Klasse definieren

<?php 
  # zuweisung_obj.php

  class Oh {        # Klasse Oh
    public $x = 44; # mit der Eigenschaft $x
  }

  ...
Eine Klassendefinition ist notwendig, um Objekte erzeugen zu können.

Objekt instanziieren und zuweisen

Der Operator new veranlasst die Instanziierung eines Objekts.
  ...
  $a = new Oh; # $a ist ein Objekt der Klasse Oh
  $b = $a;     # ein neues Objekt durch Zuweisung?
  print "Werte der Eigenschaften: "
        .$a->x.",".$b->x.PHP_EOL; // 44, 44

  # Wir ändern den Wert der Eigenschaft $b->x :
  $b->x = 123;
  print 'Werte der Eigenschaften nach Änderung von $b->x: '
        .$a->x.",".$b->x.PHP_EOL; // 123, 123

  unset($a, $b);
Die Änderung der Eigenschaft in $b ändert auch die Eigenschaft in $a.
Nach den Erfahrungen mit Referenzen auf Variablen ist dieses Ergebnis unerwartet. Seit PHP 5 liefert der Zuweisungsoperator von einem Objekt keine Kopie des Objekts, sondern erzeugt eine Referenz. $b ist also nur ein Zweitname desselben Objekts, das für $a instanziiert wurde und selbst kein neues Objekt.

Objekt kopieren

Das Erzeugen eines neuen Objekts durch Zuweisung geht aber, wenn man die vordefinierte Funktion clone() zu Hilfe nimmt. Wir erweitern das Programm mit folgendem Code.
  $c = clone($b);
  print 'Werte der Eigenschaften: '
        .$a->x.",".$b->x.",".$c->x.PHP_EOL; // 123, 123, 123

  $b->x = 51;
  print 'Werte der Eigenschaften nach erneuter Änderung von $b->x: '
        .$a->x.",".$b->x.",".$c->x.PHP_EOL; // 51, 51, 123

  unset($a, $b, $c);
Wie erwartet bei einer Objektreferenz sind die Werte $a->x und $b->x identisch, nur $c->x bleibt unbeeindruckt, weil $c ein eigenständiges Objekt der Klasse Oh ist.