Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Variable scope in functions, annoying 2

Status
Not open for further replies.

KempCGDR

Programmer
Joined
Jan 10, 2003
Messages
445
Location
GB
Ok, I have a function that reads through a table in my database where the records are meant to be displayed in a tree structure, and I want a '-' added on the start for each level, ie

Root 1
-Level 1, Item 1
-Level 1, Item 2
Root 2
-Level 1, Item 3
--Level 2 ,Item 1
-Level 1, Item 4

Each item has an id and the id of its parent stored with it so I can construct the table. Getting the things out of the database in the right order is easy, I've already done that. What I can't do is make it add the correct number of dashes. I need to have a variable that each iteration of the function has its own copy of (it's a recursive function btw) and I don't know how to define that. What I have so far is:

function showLevel($sRoot,$levelpre) {
$query = "SELECT id,name FROM uni_tree WHERE parent = $sRoot";
$Results = mysql_query($query);
If (mysql_num_rows($Results) > 0) {
while ($aResult = mysql_fetch_array($Results)) {
echo $levelPre.$aResult[name].&quot;<br>&quot;;
$levelPre .= &quot;-&quot;;
showLevel($aResult[id],$levelPre);
}
}
}

This calls itself with the id of the record it just retrieved so the next run can get the records that have that parent.

Basically it won't work properly unless either each $levelPre is local to each call or there is another easier way to do it, so my question is how? The answer is probably in the documentation, but I've searched and I couldn't find it.

Thanks in advance.
 
oh yeah, and obviously I need the same for all the variables in the function, they all need to have a seperate copy for each run.
 
O... k...

Found what I needed in the docs at last, and apparently the variables are already local to the function unless defined otherwise, so my question now is why doesn't this work?

The items in my database at the mo are (with diff names to protect data):
[ID - Name - Parent]
1 - Root 1 - 0
2 - Item 1 - 1
3 - Item 2 - 1
4 - Root 2 - 0
5 - Item 3 - 1

The function is called by showLevel(0) so it starts at the root ones. And the output it gives at the moment is:

Root 1
Item 1
-Item 2
--Item 3
-Root 2

Which makes no sense to me. Any thoughts?
 
Sorry, called with showLevel(0,&quot;&quot;);
 
I'm getting crosseyed tracing the code... but I think I would expect

Root1
-Item1
-Item2
-Item3
Root2

My only guess to your strange results is the scoping of $Results... $Results is not a variable holding information, it's a resource handle to a mysql resource, and I'm betting that's not going to be held for you through the recursion... though maybe I'm mistaken. I guess the test for that is to copy out all your info before using it. so something like
Code:
function showLevel($sRoot, $levelPre) {
  $query = &quot;SELECT id, name FROM uni_tree WHERE parent = $sRoot&quot;;
  $results = mysql_query($query);
  if (mysql_num_rows($results) > 0) {
    while ($aResult = mysql_fetch_array($results)) {
      $hold_this[] = $aResult;
    }
  }
  foreach ($hold_this as $row) {
    echo $levelPre.$row['name'].&quot;<br />&quot;;
    $levelPre .= &quot;-&quot;;
    showLevel($row['id'], $levelPre);
  }
}

But I could just be missing something simple.

-Rob

 
You know what? I REALLY hate recursive functions, especially with php's stupid scope system.

There's no easy solution to this is there?
 
Result of your idea:

root 1

Warning: Invalid argument supplied for foreach() in c:\program files\easyphp\ on line 26
-root 2

Warning: Invalid argument supplied for foreach() in c:\program files\easyphp\ on line 26
--root 3
---item 1 [parent is root 3]
----item 2 [parent is item 1]

Warning: Invalid argument supplied for foreach() in c:\program files\easyphp\ on line 26
----item 3 [parent is root 3]

Warning: Invalid argument supplied for foreach() in c:\program files\easyphp\ on line 26


the notes in square brackets are added by me (the database has changed since last time). It's just adding more '-'s on for each item it pulls out the database, though it is getting them in the right order. And then there's the errors...
 
skiflyer's code should read:
[tt]function showLevel($sRoot, $levelPre) {
$query = &quot;SELECT id, name FROM uni_tree WHERE parent = $sRoot&quot;;
$results = mysql_query($query);
$hold_this = array();
if (mysql_num_rows($results) > 0) {
while ($aResult = mysql_fetch_array($results)) {
$hold_this[] = $aResult;
}
}
foreach ($hold_this as $row) {
echo $levelPre.$row['name'].&quot;<br />&quot;;
showLevel($row['id'], $levelPre . &quot;-&quot;);
}
}[/tt]

//Daniel
 
Wow, it works, thanks man. Have I said how much I hate coding recursive functions in php yet? Anyway, I'll give you two a star, skiflyer for coming up with the code, and danielhozac for correcting it for me.

Thanks again.
 
Thanks Daniel, was on my way out the door and threw it together.

KemCGDR, I'm not sure what you find stupid about PHP's scoping, it's standard scoping. There are a few languages like VB which scope otherways, but for the most part this is the standard and accepted way of doing things.

And in fact, you had your function completely right within the scoping rules, it's just that resource handles are not the same thing as a variable.

-Rob

 
Yeah I know, but I have to take my anger out on something, can't blame myself now can I ;)

But yeah, thanks again, I really couldn't see where I was meant to be going with my code.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top