Copie de tableau en PHP : simple affectation ou clone ?

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Copie profonde d'un tableau en PHP : mythes et réalité

\n\n

Imaginez 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\n

La 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\n

Dans 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\n

Affectation directe : la première surprise

\n\n

La 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\n

En 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\n

Conclusion : pour les tableaux unidimensionnels simples, l'affectation directe est une copie complète.

\n\n

Piège : les objets à l'intérieur du tableau

\n\n

Imaginez maintenant que le tableau contienne des objets :

\n\n
class 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\n

Et 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\n

La fonction array_merge() : des nuances non évidentes

\n\n

On voit souvent le conseil d'utiliser array_merge() pour copier un tableau :

\n\n
$original = [1, 2, 3];\n$copy = array_merge([], $original);\n$copy[0] = 100;\n\nprint_r($original); // [1, 2, 3]
\n\n

Oui, 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 :

\n\n
$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\n

Vous 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\n

Conclusion : 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.

\n\n

Copie avec une boucle : gestion manuelle

\n\n

La 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\n

Pour les tableaux simples, c'est redondant. Mais si vous avez besoin de faire une copie profonde (deep copy), alors sans récurs

Blogs

Book Recommendations