Edit report at https://bugs.php.net/bug.php?id=29992&edit=1
ID: 29992
Comment by: dave dot mittner at gmail dot com
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:
Though this may not be a "bug" it's certainly dangerous and unexpected enough to
deserve the level of importance.
As has been said, people expect the behavior of block-level scoping. I don't come from Java or
C++. I've programmed PHP for over a decade. I don't expect this kind of scope treatment
because of other languages. I expect it because it's a clean and logical practice that's
far safer than the contrary. Best practice for *any* language is to assume limited scope in blocks.
I've known that since I was a teenager.
In short, this should be changed. Even if it's a hack like unsetting it, that's safer than
the current processing model. And I don't buy that "we can't change it because people
use it" crap. I've had to rewrite entire systems due to changes in how PHP works. Stuff
breaking is a risk any time you update PHP and why you should pay attention to change lists.
Previous Comments:
------------------------------------------------------------------------
[2014-06-20 22:09:56] steve at fancyguy dot com
I have done this intentionally in some very lazy prototypes.
foreach($data as $k => &v) {
if (meets_complex_precondition($k)) {
break;
}
}
// do some stuff with $v potentially modifying it later
unset($v);
Comes in handy on occasion when working recursively by reference in deep arrays. Neat trick like
'array_map(null, $arr1, $arr2)'.
------------------------------------------------------------------------
[2014-02-11 03:34:59] xjis at msn dot com
well, i guess to be more exact, i should've said php doesn't have block scope support
whereas java/c++ does.
now i see that even javascript has added block scoping starting 1.7 (need to use 'let'
instead of 'var' to declare block-scoped variables)
------------------------------------------------------------------------
[2014-02-11 00:27:18] xjis at msn dot com
guys... i read through this entire thread and now i totally get it.
this is just a weird "side-effect" of having a language being "function-level
scope" instead of "block-level scope" and with referencing support.
and as long as the language stays being 'function-level scope' that also has the
referencing support, this is the expected behavior; and there's no easy way around it.
what ppl are expecting is exactly that of a block-level scope languages: having &v not
referencing anything after for-loop block ended. that's why ppl are keep referring to
C/C++/Java because these are all block-level scope languages; and why everyone wants for-loop to
"auto-unset" the &v after for-loop block ended; that would basically emulate/mimic the
behavior of block-level scope languages; but that is simply not the expected behavior for
function-level scope languages so you can't just make a special case only for for-loop blocks
--why would you make a special exception just for for-loop; why not for the entire language? then
now, you are asking PHP language to completely change itself from being a function-level scope
language into a block-level scope language
btw, javascript is also a function-level scope language, but it doesn't have this particular
problem because it doesn't support referencing
------------------------------------------------------------------------
[2013-12-04 21:50:33] gray dot bowman at gmail dot com
Just wanted to chime in that 9 years on, this is still totally unexpected behavior. Today, two
professional developers with years experience spent a couple hours trying to figure out why an array
that was demonstrably intact had its last element corrupted for apparently no reason once entering a
foreach.
------------------------------------------------------------------------
[2013-05-21 06:38:43] email at stevemann dot net
Agreed this is not a bug, it's expected behaviour. But it's dangerous as it can slip by
without being noticed. It almost certainly means there are
thousands of sites which are exhibiting wrong behaviour because of this and no-one realises. Surely
the concept of scoping the 'as' variable to the
foreach enclosure only can't be considered bad form. It would make so much more sense to
'opt-in' to retrieving the variable outside of the enclosure
(by assigning to another persistent variable within the enclosure) rather than the current
'opt-out' system (using unset()) which, unless you happen
to have read the warning is HIGHLY DANGEROUS.
------------------------------------------------------------------------
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