У меня есть следующий код:
$data['x'] = $this->x->getResults(); $data['y'] = $data['x']; //some code here to modify $data['y'] //this causes (undesirably) $data['x] to be modified as well
Наверное, поскольку все элементы $ data сами являются ссылками, модификация $ data ['y'] также модифицирует $ data ['x'] .., который НЕ является тем, что я хочу. Я хочу, чтобы $ data ['x'] оставался прежним. Есть ли способ разыменовать элементы здесь, чтобы я мог копировать элементы по значению?
Благодарю.
Обновить: $ this-> x-> getResults (); возвращает массив объектов. Поэтому я могу сделать что-то вроде: $ data ['x'] [0] -> date_create …
Обновление : моя последняя попытка клонировать массив выглядит примерно так:
$data['x'] = $this->x->getResults(); $data['y'] = $data['y']; foreach($data['x'] as $key=>$row) { $data['y'][$key]->some_attr = clone $row->some_attr; }
Неужели я здесь? Я продолжаю получать ошибку «__clone метод, вызванный не-объектной» ошибкой. Из чтения ответов кажется, что мой лучший вариант – перебирать каждый элемент и клонировать его (это то, что я пытался сделать с этим кодом ..).
UPDATE : Просто решил это !: внутри цикла foreach мне просто нужно было изменить строку:
$data['y'][$key] = clone $row;
И это работает! Спасибо всем за помощь.
Вы можете воспользоваться тем фактом, что PHP будет разыменовывать результаты вызова функции.
Вот пример кода, который я взбивал:
$x = 'x'; $y = 'y'; $arr = array(&$x,&$y); print_r($arr); echo "<br/>"; $arr2 = $arr; $arr2[0] = 'zzz'; print_r($arr); print_r($arr2); echo "<br/>"; $arr2 = array_flip(array_flip($arr)); $arr2[0] = '123'; print_r($arr); print_r($arr2);
Результаты выглядят так:
Массив ([0] => x [1] => y) Массив ([0] => zzz [1] => y) Массив ([0] => zzz [1] => y) Массив ([0] => zzz [1] => y) Массив ([0] => 123 [1] => y)
Вы можете видеть, что результаты использования array_flip()
во время привязки $arr
к $arr2
приводят к различиям в последующих изменениях в $arr2
, так как array_flip()
заставляют разыменовывать.
Это не кажется очень эффективным, но это может сработать для вас, если $this->x->getResults()
возвращает массив:
$data['x'] = array_flip(array_flip($this->x->getResults())); $data['y'] = $data['x'];
См. Эту (неотвеченную) нить для другого примера.
Если все в вашем возвращенном массиве является объектом, однако, единственный способ скопировать объект – использовать clone()
, и вам придется перебирать через $data['x']
и клонировать каждый элемент в $data['y']
.
Пример:
$data['x'] = $this->x->getResults(); $data['y'] = array(); foreach($data['x'] as $key => $obj) { $data['y'][$key] = clone $obj; }
array_flip()
не будет работать, если значения массива не являются строками или целыми числами. Однако я нашел простое решение:
$clonedArr = (array)clone(object)$arr;
Это работает благодаря свойствам клона на объекте.
Не просто. Читайте о клоне
НО! если ваши элементы не являются объектами, а не переменными типа refence, у вас нет проблем.
Пример для ссылочных типов:
$v=11; $arr[]=&$v;
Если вы работаете с объектами, вы можете захотеть взглянуть на clone
, чтобы создать копию объекта вместо ссылки .
Вот очень короткий пример:
Во-первых, с массивом он работает по значению:
$data['x'] = array( 'a' => 'test', 'b' => 'glop', ); $data['y'] = $data['x']; $data['y'][0] = 'Hello, world!'; var_dump($data['x']); // a => test : no problem with arrays
По умолчанию, с объектами, он работает по ссылке:
$data['x'] = (object)array( 'a' => 'test', 'b' => 'glop', ); $data['y'] = $data['x']; $data['y']->a = 'Hello, world!'; var_dump($data['x']); // a => Hello, world! : objects are by ref
Но, если вы клонируете объект, вы работаете над копией:
Думаю, это ваше дело?
$data['x'] = (object)array( 'a' => 'test', 'b' => 'glop', ); $data['y'] = clone $data['x']; $data['y']->a = 'Hello, world!'; var_dump($data['x']); // a => test : no ref, because of cloning
Надеюсь это поможет,
Вы можете использовать эту функцию для копирования многомерных массивов, содержащих объекты.
<?php function arrayCopy( array $array ) { $result = array(); foreach( $array as $key => $val ) { if( is_array( $val ) ) { $result[$key] = arrayCopy( $val ); } elseif ( is_object( $val ) ) { $result[$key] = clone $val; } else { $result[$key] = $val; } } return $result; } ?>
Я просто обнаружил, что если вы просто хотите получить копию массива значений (без ссылок) из константы, вы можете просто написать:
$ new_array = (массив) (объект) self :: old_array;
Не точный ответ на вопрос OP, но он помог мне и помог кому-то другому.