Edit report at https://bugs.php.net/bug.php?id=29992&edit=1

 ID:                 29992
 Updated by:         ras...@php.net
 Reported by:        fletch at pobox dot com
 Summary:            foreach by reference corrupts the array
 Status:             Not a bug
 Type:               Bug
 Package:            Scripting Engine problem
 Operating System:   linux
 PHP Version:        5.0.1
 Block user comment: N
 Private report:     N

 New Comment:

What do you mean you con't care about the explanation?

Ok, simple question then. Do you expect this to output 3?

foreach(array(1,2,3) as $b) { }
echo $b;

If you do, then you don't want us to fix this "bug" because fixing it would 
mean 
$b is not 3 here.


Previous Comments:
------------------------------------------------------------------------
[2012-02-09 16:55:31] looris at gmail dot com

No one cares about the technical explanation about why this happens at a low 
level. I'm quite puzzled you are still in denial about this bug.

------------------------------------------------------------------------
[2012-02-09 16:49:22] ras...@php.net

No matter how you paint this, it isn't a bug. What you are really asking for is 
some sort of block-level scoping. As such, it should be proposed as a feature 
request, but it would be a major change in the language. The simplest way to 
illustrate that is to just unroll the loops. Take this example:

$a = array(1,2);
foreach($a as &$b) { }
foreach($a as $b) { }
print_r($a);

The problem here is that people find it inconsistent that the 2nd loop changes 
$a. But if we unroll the loops and write the exactly equivalent code without 
the 
foreach construct we get:

$a = array(1,2);

// First loop, $b is a reference to each element in $a
$b = &$a[0];
$b = &$a[1];

// Second loop, $b is assigned the value of each element in $a
$b = $a[0];
$b = $a[1];

Those two pieces of code are identical in every way. The thing that confuses 
people is that $b is still a reference $a[1] going into the second loop.

Since PHP doesn't have block-level scoping, there is nothing in the language 
that would permit $b to be unset between the two loops without introducing a 
major inconsistency. In fact there is plenty of code that relies on this fact 
which would break if we made such an arbitrary change.

I suppose what you are asking for is syntax along the lines of:

$a = array(1,2);
{
  local $b = &$a[0];
  $b = &$a[1];
}
{
  local $b = $a[0];
  $b = $a[1];
}

Where $b is locally scoped in each of those blocks and it might look like this 
in a foreach case:

$a = array(1,2);

foreach($a as local &$b) { }
foreach($a as local $b) { }

Without such a scoping syntax change, something as simple as:

forach(array(1,2,3) as $b) { }
echo $b;

where the code fully expects $b to be 3 would break.

------------------------------------------------------------------------
[2012-02-09 12:33:40] robbie at shapehq dot co dot uk

I feel very strongly that this behavior is wrong. It's not consistent with 
other languages and will cause great confusion!

------------------------------------------------------------------------
[2011-10-20 04:56:50] bruce at kaskubar dot com

With all due respect to those who spend their time developing, debugging, and 
explaining PHP, BALDERDASH!

Elsewhere, those of us who continue to claim "bug" are supposed to be chastened 
by all the explanations that have been provided over the years. The fact that 
the reports persist and the explanations grow is evidence contrary to the 
finding of Bogus and in support of what is expected behavior.

Fletch's example, for example, is real and reproducible through at least v5.3.2.

How in the world can it be expected for a (second) loop and its object to 
perform as though no related instructions were executed previously, and then 
for that interaction to raise its ugly head for only the last iteration? It 
cannot be. It can be explained. But so can an earthquake be. That doesn't make 
it expected.

I am unaware of any other case where prior use of a variable affects subsequent 
use of the same-named variable where its value is being explicitly reset or, as 
in the case of foreach, implicitly reset by virtue of its purpose. (That is, we 
can use $i as a loop counter here and as a file handle there and as long as we 
don't cross their purposes in the space-time continuum, all is well.)

The only bogus thing about this bug report and all its cousins is their shared 
status.

------------------------------------------------------------------------
[2011-09-02 15:13:42] publcishady at gmail dot com

If you describe how it works that's not an excuse for unexpected results. I 
understand why the last element becomes a reference, but I don't understand why 
it SHOULD become a reference. That's obviously a bug for me.

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=29992


-- 
Edit this bug report at https://bugs.php.net/bug.php?id=29992&edit=1

Reply via email to