|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2014-10-13 03:13 UTC] 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. PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 17:00:01 2025 UTC |
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++; } } } ####