php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63179 foreach: Using variable reference leads to inconsistent data
Submitted: 2012-09-28 15:16 UTC Modified: 2012-09-29 11:11 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: uli dot staerk at globalways dot net Assigned:
Status: Duplicate Package: Scripting Engine problem
PHP Version: Irrelevant OS: Linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: uli dot staerk at globalways dot net
New email:
PHP Version: OS:

 

 [2012-09-28 15:16 UTC] uli dot staerk at globalways dot net
Description:
------------
As you can see from the example, php seems to mix up variables if you use the reference in a foreach.

Despite the report bug 43806, I still think this is a bug. The variable must be set when calling foreach and must not be influenced by any previous code.

Test script:
---------------
<?php
$testdata = array(
        0 => array('foo' => 'foo'),
        1 => array('bar' => 'bar')
);
foreach($testdata as &$value) {}
foreach($testdata as $key => $value) {
        if($key == 1) {
                print_r($value);
        }
}


Expected result:
----------------
Array
(
    [bar] => bar
)


Actual result:
--------------
Array
(
    [foo] => foo
)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-09-28 21:26 UTC] notzippy at gmail dot com
A variable that is the target of a foreach should be intrinsically unset and not need a manual process to do it.
 [2012-09-29 02:52 UTC] laruence@php.net
-Status: Open +Status: Duplicate
 [2012-09-29 02:52 UTC] laruence@php.net
dup to #50485
 [2012-09-29 09:38 UTC] uli dot staerk at globalways dot net
The manual says: "On each iteration, the value of the current element is assigned to $value". 

This is not correct if you have a look at my example. The manual claims that an assignment happens, but the reference has some magic override here.

Either you must fix this "consistent" implementation, or you have to fix the documentation like "it will not be correctly assigned if $value is a reference".
 [2012-09-29 10:46 UTC] nikic@php.net
@uli: Maybe it would help you to understand the behavior if you wrote those two foreach loops out. Your code is roughly equivalent to the following:

<?php
// first loop
$value =& $testdata[0];
$value =& $testdata[1];
// second loop
$value = $testdata[0];
$value = $testdata[1];

So after the second loop $value is a reference to $testdata[1]. You could say that those two variables are synonyms. So when in the second loop you assign to $value again it is still a reference to $testdata[1]. So if you change $value, then $testdata[1] is changed too.

Personally I think that we should break the reference after the foreach loop, simply to avoid the WTF moment here. I just wanted to explain why the current behavior is consistent ;)
 [2012-09-29 11:06 UTC] notzippy at gmail dot com
I agree that this behaviour should be modified to a special case, with an automatic unset occurring at the initialization of the second loop, or at the block closure of the first loop. If you read the recommended practises it is highly recommended that this is done manually after closure of the foreach loop. I would propose that this be changed to an automatic process.
 [2012-09-29 11:11 UTC] uli dot staerk at globalways dot net
Thanks for pointing this out. I think breaking the reference is not the correct way, because an implicit unset will also have to applied to variables and will break peoples code.

I think the correct way you should fix this, is by calling an implicit unset for $key and $value when BEFORE foreach and should not break any code. If you think you are breaking code, you can issue a E_WARNING if $value is a reference being destroyed.

Can you convert this bug report into some kind of feature request? :)
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC