PHP Reference Bug?

Nickolas

Member
I have found out that when we run this code the result is below (Result B). But expected result should be

Result A:
Code:
Array
(
    [0] => Test
    [1] => Tested
    [2] => Test
)
Array
(
    [0] => Test 1
    [1] => Tested
    [2] => Test 1
)

I believe that this is pointer/reference related error.
Should we consider this as an error or PHP syntax related limitation? Because when I change the second loop's reference array name ($value) this problem disappears.

NOTE: PHP version 5.3.2, Zend Server, Linux 2.6.32-28-generic-pae

PHP:
<?php

$array = array(1 => array('Test', 'Test', 'Test'), 2 => array('Test 1', 'Test 1', 'Test 1'));

foreach ($array AS $index => &$value)
{
    $value[1] = 'Tested';
}

foreach ($array AS $index => $value)
{
    print_r($value);
}
 
?>

Result B:

Code:
Array
(
    [0] => Test
    [1] => Tested
    [2] => Test
)
Array
(
    [0] => Test
    [1] => Tested
    [2] => Test
)
 
Remember that PHP only scopes to function-level. So if you take the foreach and look at the code that's being run, it's basically this:

PHP:
$array = array(1 => array('Test', 'Test', 'Test'), 2 => array('Test 1', 'Test 1', 'Test 1'));

$value =& $array[1];
$value[1] = 'Tested';

$value =& $array[2];
$value[1] = 'Tested';

$value = $array[1]; // note this line
print_r($value);

$value = $array[2];
print_r($value);
It's not obvious, but the line noted is roughly saying $array[2] = $array[1].
 
The problem is the second foreach-loop and that the references still exist. To avoid this you should destroy them by adding:

PHP:
unset($index, $value);

You can also use different identifiers for index and value.

This is my whole test-script, you can run it with and without unset() and you will see the difference. :)

PHP:
<pre><?php

$array = array(1 => array('Test', 'Test', 'Test'), 2 => array('Test 1', 'Test 1', 'Test 1'));

print_r($array);

foreach ($array AS $index => &$value)
{
    $value[1] = 'Tested';
}

print_r($array);

unset($index, $value);

foreach ($array AS $index => $value)
{
    print_r($value);
}

?>
</pre>
 
Top Bottom