php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #14607 Nested "foreach" (on the same array variable) don't work as should
Submitted: 2001-12-19 14:46 UTC Modified: 2001-12-22 15:17 UTC
From: TheWizardRK at yahoo dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 4.0.6 OS: Windows 98
Private report: No CVE-ID: None
 [2001-12-19 14:46 UTC] TheWizardRK at yahoo dot com
I have a tree, which is loaded into a variable into the following (hopefully self-explanatory) structure:

Array(
  [1] => Array ( [parentid] => 0, [name] => 1 )
  [2] => Array ( [parentid] => 0, [name] => 2 )
  [3] => Array ( [parentid] => 1, [name] => 1_1 )
  [4] => Array ( [parentid] => 3, [name] => 1_1_1 )
  [5] => Array ( [parentid] => 3, [name] => 1_1_2 )
  [6] => Array ( [parentid] => 4, [name] => 1_1_1_1 )
  [7] => Array ( [parentid] => 1, [name] => 1_2 )
  [8] => Array ( [parentid] => 7, [name] => 1_2_1 )
  [9] => Array ( [parentid] => 2, [name] => 2_1 )
) 

This results in the following three:
+ 1
 + 1_1
  + 1_1_1
   + 1_1_1_1
  + 1_1_2
 + 1_2
  + 1_2_1
+ 2
 + 2_1

I have the following recursive function to draw this tree:

function funktzia($base,$dir)
{
  foreach($dir as $id => $item)
  {
    if ($item[parentid]==$base)
    {
      echo "<UL>\n<LI>".$item[name]."</LI><BR>\n";
      funktzia($id,$dir);
      echo "</UL>\n";
    }
  }
}

where `$base' is the current tree node id, and `$dir' is the variable which holds the tree, as described above.
The function is initially called "funktzia(0,$tree);", and the recursively calls itself.

So far so good.
But if the `$dir' variable is a by-reference parameter (i.e. "[...] &$dir [...]" instead of "[...] $dir [...]" as now), or it is defined global within the function instead of being passed as a parameter (in either way, all recursion level use the same variable) - it doesn't work.
It draw the tree only while going up levels, but stop when it's time to go back to a lower level. Or in short, the following tree is drawn instead of the full one:

+ 1
 + 1_1
  + 1_1_1
   + 1_1_1_1

It seems that when we go back to the lower "foreach" loop, the array pointer it uses already points to the end of the array (since we just finished doing a "foreach" loop on that array in the higher level).

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2001-12-19 15:00 UTC] TheWizardRK at yahoo dot com
It seems that this has been pointed out before... Sorry.
But this is still not solved (although the other bug reports about this are already marked as "closed"). :(
I only saw a solution of using "reset()" in the end of the loop, but this doesn't seem to be a good solution.
Any chances that each "foreach()" will be made to work on a new copy of the array, so that nested "foreach()" will work?
 [2001-12-19 15:17 UTC] TheWizardRK at yahoo dot com
1. Actually doing a "reset()" doesn't work at all.

2. I thought that this was a duplicate of #5052 - but now I see that there's too different variables there for each level of the nested "foreach()" - and I use the same variable.
So it seems that this is not a duplicate after all (corrent me if I'm wrong).
 [2001-12-19 18:31 UTC] mfischer@php.net
Please provide a compelte self-contained copy&paste ready script.

Feedback.
 [2001-12-20 03:13 UTC] TheWizardRK at yahoo dot com
$tree = Array(
  [1] => Array ( [parentid] => 0, [name] => '1' )
  [2] => Array ( [parentid] => 0, [name] => '2' )
  [3] => Array ( [parentid] => 1, [name] => '1_1' )
  [4] => Array ( [parentid] => 3, [name] => '1_1_1' )
  [5] => Array ( [parentid] => 3, [name] => '1_1_2' )
  [6] => Array ( [parentid] => 4, [name] => '1_1_1_1' )
  [7] => Array ( [parentid] => 1, [name] => '1_2' )
  [8] => Array ( [parentid] => 7, [name] => '1_2_1' )
  [9] => Array ( [parentid] => 2, [name] => '2_1' )
);

// Recursion using a copy of the variable each time
// WORKS
function funktzia1($base,$dir)
{
  foreach($dir as $id => $item)
  {
    if ($item[parentid]==$base)
    {
      echo
"<UL>\n<LI>".$item[name]."</LI><BR>\n";
      funktzia1($id,$dir);
      echo "</UL>\n";
    }
  }
}

// Print the tree using the first function
funktzia1(0,$tree);


// Recursion using the same variable - pass by reference (note the "&" before the "$dir")
// DOESN'T WORK
function funktzia2($base,&$dir)
{
  foreach($dir as $id => $item)
  {
    if ($item[parentid]==$base)
    {
      echo
"<UL>\n<LI>".$item[name]."</LI><BR>\n";
      funktzia2($id,$dir);
      echo "</UL>\n";
    }
  }
}

// Print the tree using the second function
funktzia2(0,$tree);
 [2001-12-22 15:17 UTC] sander@php.net
The problem with your script is that nobody has the time to look into it to understand what is does. If you can't create a real simple self-contained script which reproduces this bug, it's likely to be an error in your script, and not in PHP. 

I really think it's a bogus, you're using foreach multiple times which is messy if you don't reset() at appropriate times.
Reopen if this is not the case.
 [2003-03-27 01:13 UTC] lev at centers dot ru
I reopen this bag as 22879
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu May 02 09:01:28 2024 UTC