Cópia de array em PHP: atribuição simples ou clone?

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Cópia profunda de array em PHP: mitos e realidade

\n\n

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

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

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

Atribuição direta: a primeira surpresa

\n\n

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

Surpreendentemente, 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\n

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

Conclusão: para arrays unidimensionais simples, a atribuição direta é uma cópia completa.

\n\n

A pegadinha: objetos dentro do array

\n\n

Agora imagine que o array contém objetos:

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

Aí 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\n

A função array_merge(): detalhes não óbvios

\n\n

É comum ver a recomendação de usar array_merge() para copiar um array:

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

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

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

Percebeu? 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\n

Conclusão: array_merge() é adequado apenas para copiar arrays com chaves de string ou quando a reindexação não é um problema.

\n\n

Cópia com loop: controle manual

\n\n

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

Para arrays simples, isso é exagerado. Mas se você precisar fazer uma cópia profunda (deep copy), sem recursão

Blogs

Book Recommendations