Bug #68215 [Opn->Ver]: Behavior of foreach has changed

From: 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

« previous php.bugs (#188078) next »