Existe uma função para fazer uma cópia de uma matriz PHP para outra?
Fui queimado algumas vezes tentando copiar matrizes PHP. Eu quero copiar uma matriz definida dentro de um objeto para um global fora dele.
Existe uma função para fazer uma cópia de uma matriz PHP para outra?
Fui queimado algumas vezes tentando copiar matrizes PHP. Eu quero copiar uma matriz definida dentro de um objeto para um global fora dele.
Respostas:
No PHP, matrizes são atribuídas por cópia, enquanto objetos são atribuídos por referência. Isso significa que:
$a = array();
$b = $a;
$b['foo'] = 42;
var_dump($a);
Produzirá:
array(0) {
}
Enquanto que:
$a = new StdClass();
$b = $a;
$b->foo = 42;
var_dump($a);
Rendimentos:
object(stdClass)#1 (1) {
["foo"]=>
int(42)
}
Você pode ficar confuso com complexidades como ArrayObject
, que é um objeto que age exatamente como uma matriz. Sendo um objeto, no entanto, possui semântica de referência.
Edit: @AndrewLarsson levanta um ponto nos comentários abaixo. O PHP possui um recurso especial chamado "referências". Eles são um pouco semelhantes aos ponteiros em linguagens como C / C ++, mas não são exatamente iguais. Se sua matriz contiver referências, enquanto a própria matriz for passada por cópia, as referências ainda serão resolvidas para o destino original. É claro que esse é geralmente o comportamento desejado, mas achei que valia a pena mencionar.
$copy = $original;
. O que não funciona se os elementos da matriz são referências.
php
apresenta o resultado menos esperado , porque essa solução nem sempre funciona . $a=array(); $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
imprime array0
enquanto $a=$GLOBALS; $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
imprime array1
. Aparentemente, algumas matrizes são copiadas por referência.
O PHP copiará a matriz por padrão. Referências em PHP devem ser explícitas.
$a = array(1,2);
$b = $a; // $b will be a different array
$c = &$a; // $c will be a reference to $a
Se você possui uma matriz que contém objetos, precisa fazer uma cópia dessa matriz sem tocar no ponteiro interno e precisa que todos os objetos sejam clonados (para não modificar os originais ao fazer alterações nas cópias copiadas). array), use isso.
O truque para não tocar no ponteiro interno da matriz é garantir que você esteja trabalhando com uma cópia da matriz, e não com a matriz original (ou uma referência a ela), portanto, o uso de um parâmetro de função fará o trabalho (portanto, esta é uma função que recebe uma matriz).
Observe que você ainda precisará implementar __clone () em seus objetos se desejar que suas propriedades também sejam clonadas.
Esta função funciona para qualquer tipo de matriz (incluindo tipo misto).
function array_clone($array) {
return array_map(function($element) {
return ((is_array($element))
? array_clone($element)
: ((is_object($element))
? clone $element
: $element
)
);
}, $array);
}
__FUNCTION__
é brilhante.
Quando você faz
$array_x = $array_y;
O PHP copia a matriz, então não tenho certeza de como você se queimaria. Para o seu caso,
global $foo;
$foo = $obj->bar;
deve funcionar bem.
Para se queimar, acho que você teria que usar referências ou esperar que objetos dentro das matrizes fossem clonados.
array_merge()
é uma função na qual você pode copiar uma matriz para outra no PHP.
$a_c = array_combine(array_keys($a), array_values($a))
.
simples e faz cópias profundas quebrando todos os links
$new=unserialize(serialize($old));
Eu gosto array_replace
(ou array_replace_recursive
).
$cloned = array_replace([], $YOUR_ARRAY);
Funciona como Object.assign
no JavaScript.
$original = [ 'foo' => 'bar', 'fiz' => 'baz' ];
$cloned = array_replace([], $original);
$clonedWithReassignment = array_replace([], $original, ['foo' => 'changed']);
$clonedWithNewValues = array_replace([], $original, ['add' => 'new']);
$original['new'] = 'val';
vai resultar em
// original:
{"foo":"bar","fiz":"baz","new":"val"}
// cloned:
{"foo":"bar","fiz":"baz"}
// cloned with reassignment:
{"foo":"changed","fiz":"baz"}
// cloned with new values:
{"foo":"bar","fiz":"baz","add":"new"}
array_slice($arr, 0)
quando você não se importa com chaves array_values($arr)
? Eu estou pensando que eles podem ser mais rápidos do que pesquisar em uma matriz. Além disso, em javascript, é bastante popular usar Array.slice()
para clonar matrizes.
array_slice
e todos os outros métodos mencionados aqui funcionam muito bem. Mas se você deseja mesclar vários pares de valores-chave (como também é possível com JS-Objects via Object.assign
ou a sintaxe de propagação ), array_replace
pode ser mais útil.
array_values()
que funcionou perfeitamente para o meu caso de uso.
Se você tiver apenas tipos básicos em sua matriz, poderá fazer o seguinte:
$copy = json_decode( json_encode($array), true);
Você não precisará atualizar as referências manualmente
. Sei que não funcionará para todos, mas funcionou para mim
Como isso não foi abordado em nenhuma das respostas e agora está disponível no PHP 5.3 (assumindo que o Post Original estava usando o 5.2).
Para manter uma estrutura de matriz e alterar seus valores, prefiro usar array_replace
ouarray_replace_recursive
dependendo do meu caso de uso.
http://php.net/manual/en/function.array-replace.php
Aqui está um exemplo usando array_replace
earray_replace_recursive
demonstrando que é capaz de manter a ordem indexada e capaz de remover uma referência.
O código abaixo é escrito usando a sintaxe de matriz curta disponível desde o PHP 5.4 que substitui array()
por []
.
http://php.net/manual/en/language.types.array.php
Funciona em matrizes indexadas offset e indexadas por nome
$o1 = new stdClass;
$a = 'd';
//This is the base array or the initial structure
$o1->ar1 = ['a', 'b', ['ca', 'cb']];
$o1->ar1[3] = & $a; //set 3rd offset to reference $a
//direct copy (not passed by reference)
$o1->ar2 = $o1->ar1; //alternatively array_replace($o1->ar1, []);
$o1->ar1[0] = 'z'; //set offset 0 of ar1 = z do not change ar2
$o1->ar1[3] = 'e'; //$a = e (changes value of 3rd offset to e in ar1 and ar2)
//copy and remove reference to 3rd offset of ar1 and change 2nd offset to a new array
$o1->ar3 = array_replace($o1->ar1, [2 => ['aa'], 3 => 'd']);
//maintain original array of the 2nd offset in ar1 and change the value at offset 0
//also remove reference of the 2nd offset
//note: offset 3 and 2 are transposed
$o1->ar4 = array_replace_recursive($o1->ar1, [3 => 'f', 2 => ['bb']]);
var_dump($o1);
Resultado:
["ar1"]=>
array(4) {
[0]=>
string(1) "z"
[1]=>
string(1) "b"
[2]=>
array(2) {
[0]=>
string(2) "ca"
[1]=>
string(2) "cb"
}
[3]=>
&string(1) "e"
}
["ar2"]=>
array(4) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
array(2) {
[0]=>
string(2) "ca"
[1]=>
string(2) "cb"
}
[3]=>
&string(1) "e"
}
["ar3"]=>
array(4) {
[0]=>
string(1) "z"
[1]=>
string(1) "b"
[2]=>
array(1) {
[0]=>
string(2) "aa"
}
[3]=>
string(1) "d"
}
["ar4"]=>
array(4) {
[0]=>
string(1) "z"
[1]=>
string(1) "b"
[2]=>
array(2) {
[0]=>
string(2) "bb"
[1]=>
string(2) "cb"
}
[3]=>
string(1) "f"
}
Eu sei disso há muito tempo, mas isso funcionou para mim ..
$copied_array = array_slice($original_array,0,count($original_array));
É assim que estou copiando minhas matrizes no Php:
function equal_array($arr){
$ArrayObject = new ArrayObject($arr);
return $ArrayObject->getArrayCopy();
}
$test = array("aa","bb",3);
$test2 = equal_array($test);
print_r($test2);
Isso gera:
Array
(
[0] => aa
[1] => bb
[2] => 3
)
$test2 = $test;
? Que problema está ArrayObject
resolvendo aqui?
Cria uma cópia do ArrayObject
<?php
// Array of available fruits
$fruits = array("lemons" => 1, "oranges" => 4, "bananas" => 5, "apples" => 10);
$fruitsArrayObject = new ArrayObject($fruits);
$fruitsArrayObject['pears'] = 4;
// create a copy of the array
$copy = $fruitsArrayObject->getArrayCopy();
print_r($copy);
?>
from https://www.php.net/manual/en/arrayobject.getarraycopy.php
Defina isso:
$copy = create_function('$a', 'return $a;');
Copie $ _ARRAY para $ _ARRAY2:
$_ARRAY2 = array_map($copy, $_ARRAY);
No array php, você precisa apenas atribuí-los a outra variável para obter uma cópia desse array. Mas primeiro você precisa ter certeza do seu tipo, seja array ou arrayObject ou stdObject.
Para array php simples:
$a = array(
'data' => 10
);
$b = $a;
var_dump($b);
output:
array:1 [
"data" => 10
]
private function cloneObject($mixed)
{
switch (true) {
case is_object($mixed):
return clone $mixed;
case is_array($mixed):
return array_map(array($this, __FUNCTION__), $mixed);
default:
return $mixed;
}
}