Bug #68215 [Opn->Ver]: Behavior of foreach has changed
| From: | rasmus@php.net | Date: | Tue, 14 Oct 2014 04:24:56 +0000 |
| Subject: | Bug #68215 [Opn->Ver]: Behavior of foreach has changed | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-188078@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=68215&edit=1
ID: 68215
Updated by: rasmus@php.net
Reported by: pegasus at vaultwiki dot org
Summary: Behavior of foreach has changed
-Status: Open
+Status: Verified
Type: Bug
Package: Scripting Engine problem
Operating System: Centos 6 64-bit
PHP Version: master-Git-2014-10-13 (Git)
Block user comment: N
Private report: N
New Comment:
Yes, looks like a problem in master:
http://3v4l.org/XrVYT
Previous Comments:
------------------------------------------------------------------------
[2014-10-14 02:42:49] pegasus at vaultwiki dot org
Test script provided above.
------------------------------------------------------------------------
[2014-10-13 18:41:07] pegasus at vaultwiki dot org
It seems I may not have properly described the issue at first. I noticed this happening to code
someone else had written, and it was part of a massive library. It took many hours of trial and
error to rewrite this library as a "short" PHP script, such that it still had the same
discrepancy between PHP 5.6.0 and Master.
Test script:
####
$arr = array(
'a' => array(
'a' => 'apple',
'b' => 'banana',
'c' => 'cranberry',
'd' => 'mango',
'e' => 'pineapple'
),
'b' => array(
'a' => 'apple',
'b' => 'banana',
'c' => 'cranberry',
'd' => 'mango',
'e' => 'pineapple'
),
'c' => 'cranberry',
'd' => 'mango',
'e' => 'pineapple'
);
function test(&$child, $entry)
{
$i = 1;
foreach ($child AS $key => $fruit)
{
if (!is_numeric($key))
{
$child[$i] = $fruit;
unset($child[$key]);
$i++;
}
}
}
$i = 1;
foreach ($arr AS $key => $fruit)
{
$arr[$i] = $fruit;
if (is_array($fruit))
{
test($arr[$i], $fruit);
}
unset($arr[$key]);
$i++;
}
var_dump($arr);
####
Expect: In 5.6, this re-keys a,b,c,d,e at all array levels as 1,2,3,4,5 respectively.
Actual: In Master, this re-keys correctly on the outer-most level. On the second level, only a,b,c,d
is re-keyed.
Notes: This has something to do with the reference in the definition for function test. If we break
the reference within the function, then Master replicates the expected 5.6 behavior:
####
function test(&$child, $entry)
{
$i = 1;
$tmp = $child;
foreach ($tmp AS $key => $fruit)
{
if (!is_numeric($key))
{
$child[$i] = $fruit;
unset($child[$key]);
$i++;
}
}
}
####
------------------------------------------------------------------------
[2014-10-13 11:25:28] derick@php.net
Can you please provide a reproducible case as a short PHP script?
------------------------------------------------------------------------
[2014-10-13 03:13:07] pegasus at vaultwiki dot org
Description:
------------
Historically, foreach ($arr AS $val) has acted on a copy of $arr, in order to prevent issues if $arr
entries are modified after the loop has already begun iterating. If the current value was desired,
historically for or while loops were used instead.
However, in Master, it appears that $arr always refers to the current value of $arr. This is in
contradiction to the historical behavior. If entries are added inside the loop, foreach will keep
going for the new entries. If existing entries are otherwise modified, the $val corresponds to the
updated entry rather than the $val when the loop began.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=68215&edit=1