So $array is an array of which all elements are references.
I want to append this array to another array called $results (in a loop), but since they are references, PHP copies the references and $results is full of identical elements.
So far, the best working solution is:
$results[] = unserialize(serialize($array));
which I fear to be incredibly inefficient. Is there a better way to do this?
The getArrayCopy() function of the ArrayObject class in PHP is used to create a copy of this ArrayObject. This function returns the copy of the array present in this ArrayObject.
With regards to your first question, the array is passed by reference UNLESS it is modified within the method / function you're calling. If you attempt to modify the array within the method / function, a copy of it is made first, and then only the copy is modified.
In PHP, there are three types of arrays: Indexed arrays - Arrays with a numeric index. Associative arrays - Arrays with named keys. Multidimensional arrays - Arrays containing one or more arrays.
You can use the fact that functions dereferences results when returning, for exemple here $array_by_myclone
will still have a reference to $original
($array_by_myclone[0][0] == 'foo'
) while $array_by_assignment
will have a cloned value ($array_by_assignment[0][0] == 'bar'
)
$original = 'foo';
$array_of_reference = array(&$original);
function myclone($value)
{
return $value;
}
$array_by_myclone = array();
$array_by_myclone[] = array_map('myclone', $array_of_reference);
$array_by_assignment = array();
$array_by_assignment[] = $array_of_reference;
$original = 'bar';
var_dump($array_by_myclone[0][0]); // foo, values were cloned
var_dump($array_by_assignment[0][0]); // bar, still a reference
EDIT: I wanted to check if the comment saying unserialize(serialize())
was faster was right so I did the test using php 5.5, and it turns out this is wrong: using the serialization method is slower even with a small dataset, and the more data you have the slower it gets.
lepidosteus@server:~$ php -v
PHP 5.5.1-1~dotdeb.1 (cli) (built: Aug 3 2013 22:19:30)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies
with Zend OPcache v7.0.2-dev, Copyright (c) 1999-2013, by Zend Technologies
lepidosteus@server:~$ php reference.php 1
myclone: 0.000010 seconds
serialize: 0.000012 seconds
lepidosteus@server:~$ php reference.php 1000000
myclone: 0.398540 seconds
serialize: 0.706631 seconds
Code used:
<?php
$iterations = 1000000;
if (isset($argv[1]) && is_numeric($argv[1])) {
$iterations = max(1, (int)$argv[1]);
}
$items = array();
for ($i = 0; $i < $iterations; $i++) {
$items[] = 'item number '.$i;
}
$array_of_refs = array();
foreach ($items as $k => $v) {
$array_of_refs[] = &$items[$k];
}
function myclone($value)
{
return $value;
}
$start = microtime(true);
$copy = array_map('myclone', $array_of_refs);
$time = microtime(true) - $start;
printf("%-10s %2.6f seconds\n", 'myclone:', $time);
$start = microtime(true);
$copy = unserialize(serialize($array_of_refs));
$time = microtime(true) - $start;
printf("%-10s %2.6f seconds\n", 'serialize:', $time);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With