php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76231 while (list(x,y)=each(z)) fails after first loop
Submitted: 2018-04-18 00:34 UTC Modified: 2018-04-18 00:56 UTC
From: bmrgar at twc dot com Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 7.2.4 OS: Linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: bmrgar at twc dot com
New email:
PHP Version: OS:

 

 [2018-04-18 00:34 UTC] bmrgar at twc dot com
Description:
------------
After iterating through a key,value array with a while loop, subsequent loops through the same data fail.

Directly accessing array elements still works, as does cloning the array and looping through the new one (which will also fail after the first loop).

Test script:
---------------
$a = array("a"=>1,"b"=>2,"c"=>3);

print "\"a\" = ".$a["a"]."\n";
print "\"b\" = ".$a["b"]."\n";
print "\"c\" = ".$a["c"]."\n\n";

print "First loop:\n";
while (list($key,$value) = each($a)) { print "Key: \"$key\" = Value: $value\n"; } print "\n";

print "Second loop:\n";
while (list($key,$value) = each($a)) { print "Key: \"$key\" = Value: $value\n"; } print "\n";

print "Third loop (after copy of 'a' to 'b':\n";
$b = $a;
while (list($key,$value) = each($b)) { print "Key: \"$key\" = Value: $value\n"; } print "\n";

Expected result:
----------------
"a" = 1
"b" = 2
"c" = 3

First loop:
Key: "a" = Value: 1
Key: "b" = Value: 2
Key: "c" = Value: 3

Second loop:
Key: "a" = Value: 1
Key: "b" = Value: 2
Key: "c" = Value: 3

Third loop (after copy of 'a' to 'b':
Key: "a" = Value: 1
Key: "b" = Value: 2
Key: "c" = Value: 3


Actual result:
--------------
"a" = 1
"b" = 2
"c" = 3

First loop:
Key: "a" = Value: 1
Key: "b" = Value: 2
Key: "c" = Value: 3

Second loop:

Third loop (after copy of 'a' to 'b':
Key: "a" = Value: 1
Key: "b" = Value: 2
Key: "c" = Value: 3


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-04-18 00:45 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2018-04-18 00:45 UTC] requinix@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

If you are going to iterate over an array manually then you must use the correct procedure. The simplest form is

for (reset($array); key($array) !== null; next($array)) {
  $key = key($array);
  $value = current($array);
  ...
}

each() is deprecated so avoid using it.

Your problem is you are missing the reset(), which moves the internal pointer used by key/current/next/etc. back to the beginning of the array. Creating a copy gives you a fresh version with its pointer already at the beginning.

Or be normal and use a foreach.
 [2018-04-18 00:48 UTC] bmrgar at twc dot com
-Status: Not a bug +Status: Closed
 [2018-04-18 00:48 UTC] bmrgar at twc dot com
Ok - was still digging on this issue when I found the 'reset' array function.  I've closed this as I'm guessing the devs will say 'working as intended' due to that function.

For what it's worth, a while context should have it's own scoped iterator.  Otherwise, loops that are 'for each' do not behave as expected (i.e. actually iterating *each* element on specific runs, instead iterating of iterating none).
 [2018-04-18 00:56 UTC] requinix@php.net
-Status: Closed +Status: Not a bug
 [2018-04-18 00:56 UTC] requinix@php.net
> For what it's worth, a while context should have it's own scoped iterator.
while loops are not iterators. They are syntactic sugar around goto statements. So is foreach for that matter, but it has a bit more sugar sprinkled in.

"Expected behavior" depends on how much one knows. In this case you weren't aware of some important details.
 [2018-04-25 02:10 UTC] a at b dot c dot de
For what it's worth, there is also the syntax

foreach($a as $key=>$value) { ... }

that can be used to implement "for each" loops. This syntax doesn't use the reset/next/each array pointer mechanism.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Wed Apr 01 07:01:22 2020 UTC