php copying array elements by value, not by reference
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;
}
PHP copy array without references
If your issue is solved using the duplicate link in your question's first comment (supported by 4 others at the time I'm writing this). Please delete your question so that SO can reduce duplicate questions / needless bloat.
Otherwise, just declare a static copy of the original array for future use.
$arr = [1,2,3];
$copy=$arr; // preserve the original
print_r($arr); echo"<br>";
$x = &$arr[1];
$arr2 = $arr;
print_r($arr); print_r($arr2); echo"<br>";
$x = 8;
print_r($arr); print_r($copy); echo"<br>";
Are arrays in PHP copied as value or as reference to new variables, and when passed to functions?
For the second part of your question, see the array page of the manual, which states (quoting) :
Array assignment always involves value
copying. Use the reference operator to
copy an array by reference.
And the given example :
<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
// $arr1 is still array(2, 3)
$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>
For the first part, the best way to be sure is to try ;-)
Consider this example of code :
function my_func($a) {
$a[] = 30;
}
$arr = array(10, 20);
my_func($arr);
var_dump($arr);
It'll give this output :
array
0 => int 10
1 => int 20
Which indicates the function has not modified the "outside" array that was passed as a parameter : it's passed as a copy, and not a reference.
If you want it passed by reference, you'll have to modify the function, this way :
function my_func(& $a) {
$a[] = 30;
}
And the output will become :
array
0 => int 10
1 => int 20
2 => int 30
As, this time, the array has been passed "by reference".
Don't hesitate to read the References Explained section of the manual : it should answer some of your questions ;-)
Copy a multi-dimentional array by Value (not by reference) in PHP
if this is your real print_r output, then you have some unwanted chars in your array keys.
Array
(
[formid] => 2
[edu] => Array //<--- $_SESSION['post']['edu']
(
['id'] => Array // <---- $_SESSION['post']['edu']["'id'"]
PHP Array element assignment for readonly - is value copied?
PHP uses copy-on-write. It attempts to avoid physically copying data unless it needs to.
From PHP docs - Introduction to Variables:
PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting.
You can test this easily:
/* memory usage helpers */
$mem_initial = memory_get_usage();
$mem_last = $mem_initial;
$mem_debug = function () use ($mem_initial, &$mem_last) {
$mem_current = memory_get_usage();
$mem_change = $mem_current - $mem_last;
echo 'Memory usage change: ', $mem_change >= 0 ? '+' : '-', $mem_change, " bytes\n";
$mem_last = $mem_current;
};
/* test */
echo "Allocating 10kB string\n";
$string = str_repeat('x', 10000);
$mem_debug();
echo "\n";
echo "Copying string by direct assignment\n";
$string2 = $string;
$mem_debug();
echo "\n";
echo "Modyfing copied string\n";
$string2 .= 'x';
$mem_debug();
echo "\n";
echo "Copying string with a (string) cast\n";
$string3 = (string) $string;
$mem_debug();
Output for PHP 5.x:
Allocating 10kB string
Memory usage change: +10816 bytes
Copying string by direct assignment
Memory usage change: +56 bytes
Modyfing copied string
Memory usage change: +10048 bytes
Copying string with a (string) cast
Memory usage change: +10104 bytes
- direct assignment doesn't copy the string in memory as expected
- modifying the copied string does duplicate the string in memory - copy-on-write has happened
- assigning the string with an additional
(string)
cast seems to duplicate the string in memory even if it is unchanged
Output for PHP 7.0:
Allocating 10kB string
Memory usage change: +13040 bytes
Copying string by direct assignment
Memory usage change: +0 bytes
Modyfing copied string
Memory usage change: +12288 bytes
Copying string with a (string) cast
Memory usage change: +0 bytes
- copy-on-write behavior is the same as in the 5.x versions but meaningless
(string)
casts don't cause the string to be duplicated in memory
Why does Copy On Write not work on PHP Array which has reference element?
$b = &$a;
This is pass by reference and in other words, a new shallow copy of $a
. So, any modification in $b
will reflect in $a
and vice-versa.
Demo: https://3v4l.org/r86j4
$c = $b;
This is pass by value. So, any modification in $c
will only reflect in $c
.
$a = [1, &$x];
This is the same as the first example. The second location in the array is now a new copy of same $x
.
$x = 1;
$a = [1, &$x];
$b = $a;
$c = $b;
$c[1] = 2;
$b = $a
and $c = $b
above is pass by value. So, this assignment clones a new copy of $a
, however, the &$x
in the 2nd location is preserved.
That being said, it's never a good practice to assign variables as pass by reference to arrays individual locations(except for educational purposes). You would soon land into debugging issues and code's undefined behaviors.
All in all, if you want to create a new shallow copy, use &
, else use a simple assignment for deep copy(More info).
Update:
the 2nd location is preserved
because the second element is a reference, so it holds the reference and naturally the modification reflects everywhere. In the below example, it is pass by value.
<?php
$x = 4;
$y = &$x;
$a = [1,2,$y];
$b = $a;
$b[2] = 40;
var_dump($a);
var_dump($b);
Demo: https://3v4l.org/W9PIR
Reference vs. value copy for PHP arrays?
Let's take a closer look at
while ($colData= $meta->fetch_field()) {
$this->paramArray[]= &$this->assocArray[$colData->name];
}
call_user_func_array(array($stmt,'bind_result'),$this->paramArray);
There you have your reference(s) and that's causing the trouble. If you copy an array that contains a reference the result is still an array containing a reference.
Try
while ($row= $res->fetch()) {
var_dump($row);
and you will see that $row also contains references. All those corresponding elements in paramArray
, assocArray
and $row
actually reference the same value. And thus when you invoke return $this->stmt->fetch()
it doesn't only affect paramArray
but all those references, all the way down to $rows since $rows[]= $row;
still only copies the array but does not "de-reference" the elements.
Related Topics
Using Return in Ternary Operator
File Download Script Doesn't Work When Called from Ajax
Nested PHP Ternary Trouble: Ternary Output != If - Else
Removing Password from Rsa Private Key
Mysqli Prepared Statement Num_Rows Returns 0 While Query Returns Greater Than 0
Get the Number of Pages in a PDF Document
Is There a PHP Function for Swapping the Values of Two Variables
PHP Notice: Undefined Offset: 1 with Array When Reading Data
How to Disable Notices and Warnings in PHP Within the .Htaccess File
Php's Preg_Replace Regex That Matches Multiple Lines
Pdo Lastinsertid() Always Return 0
Uploading a File via Ajax with PHP
How to Get Around or Make PHP JSON_Decode Not Alter My Very Large Integer Values
.Htaccess Mod_Rewrite > 500 Internal Server Error
How to Get the Function Name Inside a Function in PHP
Sending Post Parameters with Postman Doesn't Work, But Sending Get Parameters Does