php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #33031 foreach fails to continue after returning from a recursion call
Submitted: 2005-05-14 03:49 UTC Modified: 2005-05-16 00:17 UTC
From: jxmaster at msn dot com Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 4.3.11 OS: windowsxp
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: jxmaster at msn dot com
New email:
PHP Version: OS:

 

 [2005-05-14 03:49 UTC] jxmaster at msn dot com
Description:
------------
'foreach' fails to continue visiting the following items in the array after returning from a recursion function call. I understand that 'foreach' works on the copy of the array, but I think it cannot explain the situation. Because after returning from the recursion call, the memory space before the call should be popped out from the running enviorenment stack. Hence, foreach should not feel that its execution has been interrupted by the recursion call.
If I change the structure of the array slightly and use for loop to replace foreach the function get the expected value. 
Following is the revised version:
function recurGetDescdendant($all, $current, $descendant) {
 $length = count($all);
 for ($i = 0; $i < $length; $i++) {
 	$userid = $all[$i][0];
 	$parent = $all[$i][1];
 	if ($parent == $current) {
    $descendant[] = $userid;
    $cdescendant = array();
    recurGetDescdendant(&$all, $userid, &$cdescendant);
    $descendant = array_merge($descendant, $cdescendant);
  }  }  }
//key represents the user id; value reprents the parent's user id of this user. for example: 6 => 1 means user 6's parent is user 1
  $all = array(array(1,0), array(2,0), array(3,0), array(4,0), array(5,0), array(6,1), array(7,1), array(11,7), array(12,11), array(13,11) );
  $descendant = array();
  recurGetDescdendant(&$all, 1, &$descendant);
  foreach ($descendant as $value) echo $value . "<br>\n";

Reproduce code:
---------------
function recurGetDescdendant($all, $current, $descendant) {
 foreach ($all as $userid => $parent) {
   if ($parent == $current) {
    $descendant[] = $userid;
    $cdescendant = array();
    recurGetDescdendant(&$all, $userid, &$cdescendant);
    $descendant = array_merge($descendant, $cdescendant);
  }  }  }
//key represents the user id; value reprents the parent's user id of this user. for example: 6 => 1 means user 6's parent is user 1
  $all = array(1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 1, 7 => 1, 11 => 7, 12 => 11, 13 => 11 );
  $descendant = array();
  recurGetDescdendant(&$all, 1, &$descendant);
  foreach ($descendant as $value) echo $value . "<br>\n";

Expected result:
----------------
6<br>
7<br>
11<br>
12<br>
13<br>

Actual result:
--------------
6<br>

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-05-14 19:30 UTC] tony2001@php.net
Please try to provide more readable reproduce code.
 [2005-05-15 02:24 UTC] jxmaster at msn dot com
Sorry for the reproduce code, but for the line limit, I have no choice. 

//--------------------------------------
// reproduce code
//--------------------------------------
function recurGetDescdendant($all, $current, $descendant)
{
 foreach ($all as $userid => $parent)
 {
   if ($parent == $current)
   {
    $descendant[] = $userid;
    $cdescendant = array();
    recurGetDescdendant(&$all, $userid, &$cdescendant);
    $descendant = array_merge($descendant, $cdescendant);
   }
 }
}
/*key represents the user id; value reprents the parent's user id of this user. for example: 6 => 1 means user 6's parent is user 1*/
$all = array(1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 1, 7 => 1, 11 => 7, 12 => 11, 13 => 11 );
$descendant = array();
recurGetDescdendant(&$all, 1, &$descendant);
foreach ($descendant as $value) echo $value . "<br>\n";
 [2005-05-16 00:17 UTC] sniper@php.net
RTFM: http://www.php.net/foreach

(that note about pointer being reset..and working with copy..)


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 30 11:01:29 2024 UTC