Tiefes Kopieren eines Arrays in PHP: Mythen und Realität
\n\nStellen Sie sich vor: Sie schreiben ein Skript, das Daten aus einer Datenbank verarbeitet. Sie erhalten ein Array mit Benutzern, arbeiten damit und stellen plötzlich fest, dass die ursprünglichen Daten geändert wurden. Kommt Ihnen das bekannt vor? Wenn Sie mit PHP arbeiten, kann dieses Problem selbst erfahrene Entwickler überraschen.
\n\nDie Frage „Is there a function to make a copy of a PHP array to another?“ auf Stack Overflow hat zehntausende Aufrufe. Und das ist kein Zufall. Auf den ersten Blick scheint das Kopieren von Arrays in PHP eine triviale Aufgabe zu sein. Aber der Teufel steckt, wie immer, im Detail.
\n\nIn diesem Artikel analysieren wir alle möglichen Methoden zum Kopieren eines Arrays in PHP: von der einfachen Zuweisung bis zur Arbeit mit mehrdimensionalen Strukturen. Sie erfahren, wann PHP eine echte Kopie erstellt und wann nur eine Referenz auf die Daten. Los geht's!
\n\nDirekte Zuweisung: Die erste Überraschung
\n\nDer intuitivste Weg ist, ein Array einfach einer anderen Variable zuzuweisen:
\n\n$original = ['apple', 'banana', 'cherry'];\n$copy = $original;\n$copy[0] = 'mango';\n\nprint_r($original);\n// Array ( [0] => apple [1] => banana [2] => cherry )\nprint_r($copy);\n// Array ( [0] => mango [1] => banana [2] => cherry )\n\nÜberraschenderweise funktioniert das! In PHP sind Arrays value types (Wertetypen), keine Referenztypen. Wenn Sie ein Array einer anderen Variable zuweisen, erstellt PHP eine flache Kopie (shallow copy) mit verzögerter Kopie (copy-on-write).
\n\nEinfach ausgedrückt: Solange Sie keines der Arrays ändern, zeigen sie auf dieselben Daten im Speicher. Sobald Sie versuchen, ein Element in einer der Variablen zu ändern, weist PHP neuen Speicher zu und kopiert die Daten. Das ist sehr effizient und erfordert keine zusätzlichen Aktionen.
\n\nFazit: Für einfache eindimensionale Arrays ist die direkte Zuweisung eine vollwertige Kopie.
\n\nFallstrick: Objekte innerhalb des Arrays
\n\nStellen Sie sich nun vor, dass sich im Array Objekte befinden:
\n\nclass User {\n public $name;\n public function __construct($name) {\n $this->name = $name;\n }\n}\n\n$original = [new User('Alice'), new User('Bob')];\n$copy = $original;\n$copy[0]->name = 'Charlie';\n\nprint_r($original[0]->name); // Charlie\n\nDa haben wir die Überraschung! Die flache Kopie hat die Referenz auf das Objekt kopiert, nicht das Objekt selbst. Wenn Sie das Objekt in der Kopie ändern, ändern Sie es auch im Original. Für Objekte ist ein anderer Ansatz erforderlich.
\n\nDie Funktion array_merge(): Nicht offensichtliche Nuancen
\n\nOft wird empfohlen, array_merge() zum Kopieren eines Arrays zu verwenden:
$original = [1, 2, 3];\n$copy = array_merge([], $original);\n$copy[0] = 100;\n\nprint_r($original); // [1, 2, 3]\n\nJa, das funktioniert. Aber es gibt eine wichtige Nuance: array_merge() setzt numerische Schlüssel zurück und nummeriert sie neu ab Null. Wenn Ihre Schlüssel Zeichenketten sind, ist alles in Ordnung. Wenn sie numerisch sind, müssen Sie mit Überraschungen rechnen:
$original = ['a' => 1, 2 => 'two', 5 => 'five'];\n$copy = array_merge([], $original);\n\nprint_r($copy);\n// Array ( [a] => 1 [0] => two [1] => five )\n\nSehen Sie? Die Schlüssel 2 und 5 wurden zu 0 und 1. Dies kann die Logik zerstören, wenn die Reihenfolge der Schlüssel wichtig ist.
\n\nFazit: array_merge() eignet sich nur zum Kopieren von Arrays mit Zeichenkettenschlüsseln oder wenn eine Neuindizierung nicht schlimm ist.
Kopieren mit einer Schleife: Manuelle Steuerung
\n\nDer zuverlässigste, aber auch der ausführlichste Weg ist, das Array mit einer Schleife zu durchlaufen:
\n\n$original = ['x' => 10, 'y' => 20];\n$copy = [];\n\nforeach ($original as $key => $value) {\n $copy[$key] = $value;\n}\n\n$copy['x'] = 100;\nprint_r($original['x']); // 10\n\nFür einfache Arrays ist das überflüssig. Aber wenn Sie eine tiefe Kopie (deep copy) erstellen müssen, dann ohne Rekurs