Copie profonde d'un tableau en PHP : mythes et réalité
\n\nImaginez la situation : vous écrivez un script qui traite des données provenant d'une base de données. Vous récupérez un tableau d'utilisateurs, vous faites quelque chose avec, puis vous découvrez soudainement que les données d'origine ont changé. Familier ? Si vous travaillez avec PHP, ce problème peut surprendre même un développeur expérimenté.
\n\nLa question « Is there a function to make a copy of a PHP array to another? » sur Stack Overflow a recueilli des dizaines de milliers de vues. Et ce n'est pas un hasard. À première vue, il semble que copier des tableaux en PHP soit une tâche triviale. Mais le diable, comme toujours, se cache dans les détails.
\n\nDans cet article, nous allons passer en revue toutes les façons possibles de copier un tableau en PHP : de la simple affectation au travail avec des structures multidimensionnelles. Vous apprendrez quand PHP crée une vraie copie, et quand il ne crée qu'une référence aux données. C'est parti !
\n\nAffectation directe : la première surprise
\n\nLa méthode la plus intuitive est simplement d'affecter le tableau à une autre variable :
\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Étonnamment, cela fonctionne ! En PHP, les tableaux sont des value types (types de valeurs), et non des types de référence. Lorsque vous affectez un tableau à une autre variable, PHP crée une copie superficielle (shallow copy) avec une copie différée (copy-on-write).
\n\nEn termes simples : tant que vous ne modifiez aucun des tableaux, ils pointent vers les mêmes données en mémoire. Dès que vous essayez de modifier un élément dans l'une des variables, PHP alloue une nouvelle mémoire et copie les données. C'est très efficace et ne nécessite aucune action supplémentaire.
\n\nConclusion : pour les tableaux unidimensionnels simples, l'affectation directe est une copie complète.
\n\nPiège : les objets à l'intérieur du tableau
\n\nImaginez maintenant que le tableau contienne des objets :
\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\nEt voilà la surprise ! La copie superficielle a copié la référence vers l'objet, et non l'objet lui-même. En modifiant l'objet dans la copie, vous le modifiez dans l'original. Pour les objets, une autre approche est nécessaire.
\n\nLa fonction array_merge() : des nuances non évidentes
\n\nOn voit souvent le conseil d'utiliser array_merge() pour copier un tableau :
$original = [1, 2, 3];\n$copy = array_merge([], $original);\n$copy[0] = 100;\n\nprint_r($original); // [1, 2, 3]\n\nOui, cela fonctionne. Mais il y a une nuance importante : array_merge() réinitialise les clés numériques et les renumérote à partir de zéro. Si vos clés sont des chaînes de caractères, tout va bien. Mais si elles sont numériques, préparez-vous à des surprises :
$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\nVous voyez ? Les clés 2 et 5 sont devenues 0 et 1. Cela peut casser la logique si l'ordre des clés est important.
\n\nConclusion : array_merge() ne convient que pour copier des tableaux avec des clés de type chaîne de caractères ou lorsque la réindexation n'est pas un problème.
Copie avec une boucle : gestion manuelle
\n\nLa méthode la plus fiable, mais aussi la plus verbeuse, est de parcourir le tableau avec une boucle :
\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\nPour les tableaux simples, c'est redondant. Mais si vous avez besoin de faire une copie profonde (deep copy), alors sans récurs