php按值复制数组元素,而不是通过引用

时间:2009-07-27 19:11:39

标签: php arrays codeigniter pointers

我有以下代码:

$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;

它有效!感谢大家的帮助。

6 个答案:

答案 0 :(得分:10)

您可以利用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);

结果如下:

Array ( [0] => x [1] => y )
Array ( [0] => zzz [1] => y ) Array ( [0] => zzz [1] => y )
Array ( [0] => zzz [1] => y ) Array ( [0] => 123 [1] => y ) 

您可以看到在array_flip()$arr的分配过程中使用$arr2的结果导致$arr2的后续更改存在差异,因为{{1}调用强制取消引用。

它看起来效率不高,但如果array_flip()返回一个数组,它可能对您有用:

$this->x->getResults()

有关其他示例,请参阅this (unanswered) thread

如果返回的数组中的所有内容都是对象,那么复制对象的唯一方法是使用$data['x'] = array_flip(array_flip($this->x->getResults())); $data['y'] = $data['x']; ,您必须遍历clone()并将每个元素克隆到{{} 1}}。

示例:

$data['x']

答案 1 :(得分:6)

当数组值不是字符串或整数时,

array_flip()将不起作用。 然而,我找到了一个简单的解决方案:

$clonedArr = (array)clone(object)$arr;

这要归功于对象上克隆的属性。

答案 2 :(得分:3)

不简单。 阅读clone

BUT!如果您的元素不是对象不是refence类型变量,则没有问题。

参考类型示例:

$v=11;
$arr[]=&$v;

答案 3 :(得分:2)

如果您正在使用对象,则可能需要查看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

希望这有帮助,

答案 4 :(得分:0)

您可以使用此函数复制包含对象的多维数组。

<?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;
}
?>

答案 5 :(得分:0)

我刚刚发现,如果你只想要一个常量值的数组(没有引用)的副本,那么你可以写:

$ new_array =(array)(object)self :: old_array;

对于OP的问题不是一个确切的答案,但它帮助了我,可能会帮助其他人。