php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #29686 Bug when using foreach on an array that has been referenced before
Submitted: 2004-08-15 12:37 UTC Modified: 2005-04-14 09:49 UTC
Votes:2
Avg. Score:1.0 ± 0.0
Reproduced:1 of 2 (50.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: swalk at prp dot physik dot tu-darmstadt dot de Assigned: et (profile)
Status: Closed Package: Documentation problem
PHP Version: 5.* OS: *
Private report: No CVE-ID: None
 [2004-08-15 12:37 UTC] swalk at prp dot physik dot tu-darmstadt dot de
Description:
------------
When using foreach with an array that has been referenced before, it behaves oddly if you re-set the variable inside the loop - it loses the array it originally worked on. That doesn't happen if you leave the line creating the reference out.

Reproduce code:
---------------
<?php
$a = array(1,2,3);
$b =& $a; // this line causes the bug
          // $a =& $a; does it too
foreach($a as $v) {
    print "$v\n";
    $a = "foo"; 
}


Expected result:
----------------
1
2
3

Actual result:
--------------
1

Warning: Invalid argument supplied for foreach() in /home/et/test.php on line 4

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-08-15 14:55 UTC] jakub dot phpbug at horky dot net
I'm afraid that is caused just by the line
    $a = "foo";
which re-sets the $a variable to string, so it is no longer an array and can't be enumerated by next loop...
 [2004-08-15 15:05 UTC] et@php.net
Please read properly before posting. And also read 
http://www.php.net/foreach , especially the part with "Note:  Also note that foreach operates on a copy of the specified array and not the array itself."

And as was said, it only happens if you do $a =& $a; before the foreach clause. If you don't do it, you get the expected result.
 [2004-08-15 15:07 UTC] helly@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

.
 [2004-08-15 15:20 UTC] et@php.net
Care to explain why doing $a =& $a; before the loop should affect the behaviour? In my (and some others whom i talked to) opinion that behaviour is bogus. And if it does make sense, it should be reflected in the documentation (where it isn't), because this caused someone an error with a high WTF factor in an application.
Example:
foreach ($_SESSION['something'] as $foo) {
    do_something;
    $something = "foo";
    do_something_else;
}
Breaks on a server with register_globals on.
    
 [2004-08-15 15:27 UTC] helly@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

Don't use register globals. And don't use it for example because of this problem.

Second, a reference variable and a normal variable do NOT result in foreach copying the whole array. Instaed not accessing the data by ref [foreach($ar as &$data)] only results in copying the data. Therefor the array is still ste same and if you change the array in the loop then obviously you affect the loop.
 [2004-08-15 15:40 UTC] jakub dot phpbug at horky dot net
To et@php.net:

> especially the part with "Note:  Also note
> that foreach operates on a copy of the specified
> array and not the array itself."

Sorry, but that especially this paragraph is very obscure, because a subsequent sentence states "However, the internal pointer of the original array is advanced with the processing of the array."

Furthermore, this is partially subject of recently opened bug #28939 or #28939.

But there I really don't see any problem. Coincidental overwriting of registered global is IMO really not bug but stupidity of the author :-)
 [2004-08-15 15:42 UTC] jakub dot phpbug at horky dot net
Sorry for mistyping the bug numbers: bug #28939 and bug #29687
 [2004-08-15 15:44 UTC] et@php.net
I don't use register globals. But there are lots of servers which do.
1st, you're contradicting the Documentation, which clearly states that the array should be copied: "Note:  Also note that foreach operates on a copy of the specified array and not the array itself."
2nd, you didn't specify the difference between using a reference variable and a normal variable.
If you do 
foreach($array as $v) {
   array_push($array, 0);
}
modifying the array, it doesn't affect the loop. By your reasoning, it should?

Please don't bogus it again, because it is either a problem with the documentation or with the implementation.
 [2004-08-15 16:09 UTC] jakub dot phpbug at horky dot net
Yes, sorry, now I see you are true. When I tested the example above I didn't try to comment out the line '$b =& $a;' so I thought the array is always using directly from foreach on each loop. So IMHO there is either badly written documentation or bad implementation (which is btw relevant to that two bugs I posted before).

BUG UPDATE: Now I noticed that if you first unset() the $a variable before re-setting it to the string (or anything else), it is working properly.
 [2005-02-15 00:22 UTC] tony2001@php.net
Stefan, please look into it.
If it works as expected, than it's a docu problem, probably.
 [2005-04-14 09:49 UTC] vrana@php.net
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation better.

"Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself."
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 17 23:01:28 2024 UTC