Чи є функція зробити копію масиву PHP до іншого?
Мене кілька разів спалювали, намагаючись скопіювати масиви PHP. Я хочу скопіювати масив, визначений всередині об'єкта, у глобальний поза ним.
Чи є функція зробити копію масиву PHP до іншого?
Мене кілька разів спалювали, намагаючись скопіювати масиви PHP. Я хочу скопіювати масив, визначений всередині об'єкта, у глобальний поза ним.
Відповіді:
У PHP масиви призначаються копією, а об'єкти присвоюються посиланням. Це означає що:
$a = array();
$b = $a;
$b['foo'] = 42;
var_dump($a);
Вийде:
array(0) {
}
При цьому:
$a = new StdClass();
$b = $a;
$b->foo = 42;
var_dump($a);
Врожайність:
object(stdClass)#1 (1) {
["foo"]=>
int(42)
}
Ви можете заплутатися в тонкощах, таких як ArrayObject
, який є об'єктом, який діє точно як масив. Однак, будучи об'єктом, він має референтну семантику.
Редагувати: @AndrewLarsson ставить крапку в коментарях нижче. PHP має спеціальну функцію під назвою "посилання". Вони дещо схожі на покажчики на таких мовах, як C / C ++, але не зовсім однакові. Якщо ваш масив містить посилання, то, хоча сам масив передається копією, посилання все одно вирішать вихідну ціль. Це звичайно бажана поведінка, але я вважав, що це варто згадати.
$copy = $original;
. Що не працює, якщо елементи масиву є посиланнями.
php
дає нам найменш очікуваний результат , адже це рішення не завжди працює . $a=array(); $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
друкує array0
під час $a=$GLOBALS; $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
друку array1
. Мабуть, деякі масиви копіюються за посиланням.
PHP копіює масив за замовчуванням. Посилання в PHP повинні бути явними.
$a = array(1,2);
$b = $a; // $b will be a different array
$c = &$a; // $c will be a reference to $a
Якщо у вас є масив, що містить об’єкти, вам потрібно зробити копію цього масиву, не торкаючись його внутрішнього вказівника, і вам потрібно клонувати всі об'єкти (щоб ви не змінювали оригінали під час внесення змін у скопійоване масив), використовуйте це.
Трюк у тому, щоб не торкатися внутрішнього вказівника масиву, полягає в тому, щоб переконатися, що ви працюєте з копією масиву, а не з оригінальним масивом (або посиланням на нього), тож за допомогою параметра параметра ви будете виконати роботу (таким чином, це функція, яка приймає масив).
Зауважте, що вам все одно потрібно буде застосувати __clone () на своїх об'єктах, якщо ви хочете, щоб їхні властивості також були клоновані.
Ця функція працює для будь-якого типу масиву (включаючи змішаний тип).
function array_clone($array) {
return array_map(function($element) {
return ((is_array($element))
? array_clone($element)
: ((is_object($element))
? clone $element
: $element
)
);
}, $array);
}
__FUNCTION__
геніальне.
Коли ви робите
$array_x = $array_y;
PHP копіює масив, тому я не впевнений, як би ви отримали спалення. Для вашого випадку
global $foo;
$foo = $obj->bar;
повинні добре працювати.
Для того, щоб отримати опік, я б подумав, що вам або доведеться використовувати посилання або очікувати клонування об'єктів всередині масивів.
array_merge()
це функція, за допомогою якої можна копіювати один масив в інший в PHP.
$a_c = array_combine(array_keys($a), array_values($a))
.
простий і робить глибоку копію, порушуючи всі посилання
$new=unserialize(serialize($old));
Мені подобається array_replace
(або array_replace_recursive
).
$cloned = array_replace([], $YOUR_ARRAY);
Це працює як Object.assign
у 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';
призведе до
// 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)
або коли вам не байдужі ключі array_values($arr)
? Я думаю, що вони можуть бути швидшими, ніж пошук у масиві. Також у javascript досить популярно використовувати Array.slice()
для клонування масивів.
array_slice
та всі інші методи, згадані тут, працюють дуже добре. Але якщо ви хочете об'єднати кілька пар ключів-значень (як це можливо і з JS-об’єктами через Object.assign
або синтаксисом спред ), array_replace
може бути кориснішим.
array_values()
яка чудово працювала для мого використання.
Якщо у вашому масиві є лише основні типи, ви можете зробити це:
$copy = json_decode( json_encode($array), true);
Вам не потрібно буде оновлювати посилання вручну.
Я знаю, що це не буде працювати для всіх, але це працювало для мене
Оскільки це не було висвітлено в жодній з відповідей і тепер доступне в PHP 5.3 (припускається, що в Оригінальній публікації використовується 5.2).
Щоб підтримувати структуру масиву та змінювати його значення, я вважаю за краще використовувати array_replace
або array_replace_recursive
залежно від мого випадку використання
http://php.net/manual/en/function.array-replace.php
Ось приклад використання array_replace
таarray_replace_recursive
демонструє, що він може підтримувати індексований порядок і здатний видаляти посилання.
Код нижче пишеться з використанням синтаксису короткого масиву, доступного з PHP 5.4, який замінює array()
на []
.
http://php.net/manual/en/language.types.array.php
Працює на зсувних індексованих і іменованих масивах
$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);
Вихід:
["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"
}
Я це знаю як давно, але це працювало для мене ..
$copied_array = array_slice($original_array,0,count($original_array));
Ось так я копіюю свої масиви в Php:
function equal_array($arr){
$ArrayObject = new ArrayObject($arr);
return $ArrayObject->getArrayCopy();
}
$test = array("aa","bb",3);
$test2 = equal_array($test);
print_r($test2);
Цей результат:
Array
(
[0] => aa
[1] => bb
[2] => 3
)
$test2 = $test;
? Яка проблема ArrayObject
тут вирішується ?
Створює копію 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);
?>
з https://www.php.net/manual/en/arrayobject.getarraycopy.php
Визначте це:
$copy = create_function('$a', 'return $a;');
Скопіюйте $ _ARRAY в $ _ARRAY2:
$_ARRAY2 = array_map($copy, $_ARRAY);
У масиві php вам потрібно просто призначити їх іншій змінній, щоб отримати копію цього масиву. Але спершу вам потрібно переконатися, що це тип, чи це array або arrayObject чи stdObject.
Для простого масиву php:
$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;
}
}