Cópia profunda de array em PHP: mitos e realidade
\n\nImagine a situação: você está escrevendo um script que processa dados do banco. Você obtém um array de usuários, faz algo com ele e, de repente, descobre que os dados originais foram alterados. Familiar? Se você trabalha com PHP, esse problema pode pegar até mesmo um desenvolvedor experiente de surpresa.
\n\nA pergunta «Existe uma função para fazer uma cópia de um array PHP para outro?» no Stack Overflow acumulou dezenas de milhares de visualizações. E não é à toa. À primeira vista, parece que copiar arrays em PHP é uma tarefa trivial. Mas o diabo, como sempre, está nos detalhes.
\n\nNeste artigo, vamos explorar todas as formas possíveis de copiar um array em PHP: desde a atribuição simples até o trabalho com estruturas multidimensionais. Você vai descobrir quando o PHP cria uma cópia real e quando apenas uma referência aos dados. Vamos nessa!
\n\nAtribuição direta: a primeira surpresa
\n\nA maneira mais intuitiva é simplesmente atribuir o array a outra variável:
\n\n$original = ['maçã', 'banana', 'cereja'];\n$copia = $original;\n$copia[0] = 'manga';\n\nprint_r($original);\n// Array ( [0] => maçã [1] => banana [2] => cereja )\nprint_r($copia);\n// Array ( [0] => manga [1] => banana [2] => cereja )\n\nSurpreendentemente, funciona! Em PHP, arrays são tipos de valor (value types), não tipos de referência. Quando você atribui um array a outra variável, o PHP cria uma cópia superficial (shallow copy) com cópia sob demanda (copy-on-write).
\n\nEm termos simples: enquanto você não modificar nenhum dos arrays, eles apontam para os mesmos dados na memória. Assim que você tenta alterar um elemento em uma das variáveis, o PHP aloca nova memória e copia os dados. Isso é muito eficiente e não requer ações extras.
\n\nConclusão: para arrays unidimensionais simples, a atribuição direta é uma cópia completa.
\n\nA pegadinha: objetos dentro do array
\n\nAgora imagine que o array contém objetos:
\n\nclass Usuario {\n public $nome;\n public function __construct($nome) {\n $this->nome = $nome;\n }\n}\n\n$original = [new Usuario('Ana'), new Usuario('João')];\n$copia = $original;\n$copia[0]->nome = 'Carlos';\n\nprint_r($original[0]->nome); // Carlos\n\nAí está a surpresa! A cópia superficial copiou a referência ao objeto, e não o objeto em si. Ao modificar o objeto na cópia, você o altera no original. Para objetos, é necessária uma abordagem diferente.
\n\nA função array_merge(): detalhes não óbvios
\n\nÉ comum ver a recomendação de usar array_merge() para copiar um array:
$original = [1, 2, 3];\n$copia = array_merge([], $original);\n$copia[0] = 100;\n\nprint_r($original); // [1, 2, 3]\n\nSim, funciona. Mas há um detalhe importante: array_merge() redefine as chaves numéricas e as renumera a partir de zero. Se suas chaves forem strings, tudo bem. Mas se forem numéricas, prepare-se para surpresas:
$original = ['a' => 1, 2 => 'dois', 5 => 'cinco'];\n$copia = array_merge([], $original);\n\nprint_r($copia);\n// Array ( [a] => 1 [0] => dois [1] => cinco )\n\nPercebeu? As chaves 2 e 5 se transformaram em 0 e 1. Isso pode quebrar a lógica se a ordem das chaves for importante.
\n\nConclusão: array_merge() é adequado apenas para copiar arrays com chaves de string ou quando a reindexação não é um problema.
Cópia com loop: controle manual
\n\nA maneira mais confiável, embora mais verbosa, é percorrer o array com um loop:
\n\n$original = ['x' => 10, 'y' => 20];\n$copia = [];\n\nforeach ($original as $chave => $valor) {\n $copia[$chave] = $valor;\n}\n\n$copia['x'] = 100;\nprint_r($original['x']); // 10\n\nPara arrays simples, isso é exagerado. Mas se você precisar fazer uma cópia profunda (deep copy), sem recursão