|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2003-01-16 20:05 UTC] vdvo at vdvo dot net
Try this:
<?php
$a = array(1, 2);
$ref =& $a;
foreach ($ref as $b) {
echo "outer: $b<br>\n";
foreach ($a as $c)
echo "-- inner: $c<br>\n";
}
?>
The output is:
outer: 1
-- inner: 1
-- inner: 2
(i.e., the processing stops after the first iteration of the outer foreach). If I understand the docs well, the output should be:
outer: 1
-- inner: 1
-- inner: 2
outer: 2
-- inner: 1
-- inner: 2
When you remove the ampersand from the assignment to $ref, it works as expected.
The documentation is a bit unclear on this. It says "Also note that foreach operates on a copy of the specified array, not the array itself, therefore the array pointer is not modified as with the each() construct...", which leads me to believe that the sample code should work. But then it goes on to say: "However, the internal pointer of the original array *is* advanced with the processing of the array.", which seems to contradict the first quotation???
This is probably a dupe of bug #14607, but that one is closed as "bogus" and I can't reopen it. Also see bug #5052, which is similar but not quite, and it's closed.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 02:00:01 2025 UTC |
> Marking this as a documentation problem. I was sooo very much afraid you would do exactly this! :-( So it is really intended to work like this? You don't find there is anything wrong with the foreach construct? Consider this: this means that you CAN'T use foreach at all in cases where you don't know for certain whether you couldn't have possibly been called from a foreach over the same array (or a reference to it, in fact). Also, you CAN'T use foreach in a case like mine, in which I found this problem: foreach ($obj->arr as $elem) { ... $obj->method($elem); ... } What if the method also wants to iterate over the array? You don't know, it wasn't you who wrote the class library... Also, I find this very inconsistent. I didn't mention it in the original description, but you know what? When you nest two foreach's using the VERY SAME variable, it magically works! How is it possible that two references to the same variable are somehow more equivalent than the variable is to itself??? :-o No, I don't agree that this is just a documentation problem. Marking as a scripting engine problem again. You may disagree, of course, but please, give it a thought. Or perhaps some discussion. Thanks.Although I admit that the behaviour is quite inconsistent, we won't fix this anyway because the issue's all up to the language design. > Also, I find this very inconsistent. I didn't mention it in the original > description, but you know what? When you nest two foreach's using the > VERY SAME variable, it magically works! How is it possible that two > references to the same variable are somehow more equivalent than the > variable is to itself??? :-o Well, it looks like a magic. To say more precisely, foreach statement always makes use of a copy of the given array instead of the original itself unless the array is a reference or has a reference. That's the reason you could get along with nested foreach loops in general case. Thus the following while loop (A) is an equivalent to (B). <?php /* A */ $copy_foo = $a; reset($copy_foo); while (list(,$b) = each($copy_foo)) { $copy_bar = $a; reset($copy_bar); while (list(,$c) = each($copy_bar)) { print $c; } } ?> <?php /* B */ $a = array(1, 2); foreach ($a as $b) { foreach ($a as $c) { print $c; } } ?> Related bugs: http://bugs.php.net/bug.php?id=8353No matter what you call this, as a convention of open-source projects, documentation is generally supposed to come up after coding stuff. In other words, the codes determine the design, and the documents are often elusive as there are some cases where they don't reflect the actual behaviour. Regarding the nastiness of references, it's special not only for foreach, but also for the following case. <pre><?php $foo = array('test'); $bar = &$foo[0]; print "{$foo[0]}\n"; function test($foo) { $foo[0] = '???'; } test($foo); print "{$foo[0]}\n"; ?></pre> Surprisingly, this script results in ------ test ??? ------ For more about this, see bug #20993 (this is also marked as a doc-problem).