php copying array elements by value, not by reference

前端 未结 6 1977
清歌不尽
清歌不尽 2020-12-06 05:48

I have the following code:

$data[\'x\'] = $this->x->getResults();  

$data[\'y\'] = $data[\'x\'];

//some code here to modify $data[\'y\']
//this cause         


        
相关标签:
6条回答
  • 2020-12-06 06:04

    You could use this function to copy multidimensional arrays containing objects.

    <?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;
    }
    ?>
    
    0 讨论(0)
  • 2020-12-06 06:09

    You can take advantage of the fact that PHP will dereference the results of a function call.

    Here's some example code I whipped up:

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

    The results look like this:

    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 ) 
    

    You can see that the results of using array_flip() during the assigment of $arr to $arr2 results in differences in the subsequent changes to $arr2, as the array_flip() calls forces a dereference.

    It doesn't seem terribly efficient, but it might work for you if $this->x->getResults() is returning an array:

    $data['x'] = array_flip(array_flip($this->x->getResults()));
    $data['y'] = $data['x'];
    

    See this (unanswered) thread for another example.

    If everything in your returned array is an object however, then the only way to copy an object is to use clone(), and you would have to iterate through $data['x'] and clone each element into $data['y'].

    Example:

    $data['x'] = $this->x->getResults();
    $data['y'] = array();
    foreach($data['x'] as $key => $obj) {
        $data['y'][$key] = clone $obj;
    }
    
    0 讨论(0)
  • 2020-12-06 06:15

    If you are working with objects, you might want to take a look at clone, to create a copy of an object, instead of a reference.

    Here is a very short example :

    First, with an array, it works by value :

    $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
    

    By default, with objects, it works by reference :

    $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
    

    But, if you clone the object, you work on a copy :
    I guess this is your case ?

    $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
    

    Hope this helps,

    0 讨论(0)
  • 2020-12-06 06:19

    array_flip() won't work when array values are not strings nor integers. I found a simple solution, however:

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

    This works thanks to the properties of clone on an object.

    0 讨论(0)
  • 2020-12-06 06:21

    Not simple. Read about clone

    BUT! if your elements are not objects and not refence type variables you have no problem.

    Example for reference types:

    $v=11;
    $arr[]=&$v;
    
    0 讨论(0)
  • 2020-12-06 06:22

    I just discovered that if you simply want a copy of an array of values (no references) from a constant then you can just write:

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

    Not an exact answer to the OP's question but it helped me and might help someone else.

    0 讨论(0)
提交回复
热议问题