Connecting Tech Pros Worldwide Forums | Help | Site Map

PHP behaves strange when capturing 'return' value, how to over come?

Newbie
 
Join Date: Aug 2008
Posts: 4
#1: Aug 7 '08
PHP behaves strange when capturing 'return' value, how to over come?

when i echo the value inside the function, it works fine.
if i return a value from the function, it return nothing... why?

Assume, that the following is the table 'menu' and having the following fields(with values)
Expand|Select|Wrap|Line Numbers
  1. menuid        
  2. ======
  3. 1         
  4. 2        
  5. 3         
  6. 4          
  7. 5
  8. parentmenuid
  9. ==========
  10.  
  11. 1
  12. 1
  13. 5
  14. 1
  15.  
//php code
Expand|Select|Wrap|Line Numbers
  1. <?
  2. include "db.php";
  3.  
  4. $returnval=trace_child(1,4);
  5. echo $returnval;
  6.  
  7. function trace_child($parent,$child)
  8. {
  9.  $result = mysql_query('SELECT * FROM menu
  10.                           WHERE parentmenuid='.$parent);    
  11.  
  12.     while ($row = mysql_fetch_array($result)) 
  13.     {  
  14.          if($child==$row['menuid'])
  15.          {
  16.             return true;     ///the problem is here.. if i put  echo 'true';  then  it works fine... why
  17.         }
  18.          else{
  19.             trace_child($row['menuid'],$child);}    
  20.     }    
  21. }
  22.  
  23. ?>
  24.  
i wants to trace whether menu '4' is grandchild of menu'1' .
please somebody help me...

Atli's Avatar
Moderator
 
Join Date: Nov 2006
Location: Iceland
Posts: 3,751
#2: Aug 7 '08

re: PHP behaves strange when capturing 'return' value, how to over come?


Hi. Welcome to Bytes!

When you echo a Boolean value, you won't get "true" or "false". You will either get "1" if it is true, or simply nothing if it is false.

You need to use the value, like:
Expand|Select|Wrap|Line Numbers
  1. if(functionCall()) {
  2.   echo "true";
  3. }
  4. else {
  5.   echo "false";
  6. }
  7.  
P.S.
Please use [code] tags when posting code examples.
Newbie
 
Join Date: Aug 2008
Posts: 4
#3: Aug 8 '08

re: PHP behaves strange when capturing 'return' value, how to over come?


Quote:

Originally Posted by Atli

Hi. Welcome to Bytes!

When you echo a Boolean value, you won't get "true" or "false". You will either get "1" if it is true, or simply nothing if it is false.

You need to use the value, like:

Expand|Select|Wrap|Line Numbers
  1. if(functionCall()) {
  2.   echo "true";
  3. }
  4. else {
  5.   echo "false";
  6. }
  7.  
P.S.
Please use [code] tags when posting code examples.


Hi Mr. Atli,
i have tried that too.
still no use...
Actually, when we look at the above code it seems very fine...
But when we pass the function output to a variable i fails...( it is success when i use 'echo' instead of 'return')...

Mr.Atli,
Please do me a favour...
create a table(menu) that i mentioned previously, and also the field values...
now execute the above code(my php code)... Now u will know what i am trying to say...
Atli's Avatar
Moderator
 
Join Date: Nov 2006
Location: Iceland
Posts: 3,751
#4: Aug 8 '08

re: PHP behaves strange when capturing 'return' value, how to over come?


Ahh ok now I see.

The problem is the recursive call in your function doesn't return it's value.

Consider this:
Expand|Select|Wrap|Line Numbers
  1. function testFunc($value) {
  2.   if($value == 2) {
  3.     return true;
  4.   }
  5.   else {
  6.     ++$value;
  7.     testFunc($value);
  8.   }
  9. }
  10.  
  11. var_dump(testFunc(1));
  12. # Prints: NULL
  13.  
Now this function will check the value first, which is 1 in the first run. After the first if() fails, it increments and calls itself again. This time the value is 2, so it returns true.

The problem there is that the second call is the only one to return anything. You don't do anything with the results returned by that call (The recursive call, where the function calls itself).

As a result, the result is disregarded in the original call and the function returns NULL.

To fix this, in my example, you would have to add the return keyword to the second call:
Expand|Select|Wrap|Line Numbers
  1. function testFunc($value) {
  2.   if($value == 2) {
  3.     return true;
  4.   }
  5.   else {
  6.     ++$value;
  7.     return testFunc($value); # Change is here
  8.   }
  9. }
  10.  
  11. var_dump(testFunc(1));
  12. # Prints: bool(true)
  13.  
In your function, you would have to check the return value of the recursive call. If it is true, return it. If it is not, continue the while loop and return false once the loop has ended.
Newbie
 
Join Date: Aug 2008
Posts: 4
#5: Aug 10 '08

re: PHP behaves strange when capturing 'return' value, how to over come?


Quote:

Originally Posted by Atli

Ahh ok now I see.

The problem is the recursive call in your function doesn't return it's value.

Consider this:

Expand|Select|Wrap|Line Numbers
  1. function testFunc($value) {
  2.   if($value == 2) {
  3.     return true;
  4.   }
  5.   else {
  6.     ++$value;
  7.     testFunc($value);
  8.   }
  9. }
  10.  
  11. var_dump(testFunc(1));
  12. # Prints: NULL
  13.  
Now this function will check the value first, which is 1 in the first run. After the first if() fails, it increments and calls itself again. This time the value is 2, so it returns true.

The problem there is that the second call is the only one to return anything. You don't do anything with the results returned by that call (The recursive call, where the function calls itself).

As a result, the result is disregarded in the original call and the function returns NULL.

To fix this, in my example, you would have to add the return keyword to the second call:
Expand|Select|Wrap|Line Numbers
  1. function testFunc($value) {
  2.   if($value == 2) {
  3.     return true;
  4.   }
  5.   else {
  6.     ++$value;
  7.     return testFunc($value); # Change is here
  8.   }
  9. }
  10.  
  11. var_dump(testFunc(1));
  12. # Prints: bool(true)
  13.  
In your function, you would have to check the return value of the recursive call. If it is true, return it. If it is not, continue the while loop and return false once the loop has ended.

Hi Mr.Atli,
I was Very happy with your code when i when i got success for the above condition. But the program FAILS when it got morethan one child!
for example:
Condition: #2 (for Menu table)
Expand|Select|Wrap|Line Numbers
  1. menuid(field1)
  2. =====
  3. 1
  4. 2
  5. 3
  6. 4
  7. 5
  8.  
  9. parentmenuid(field2)
  10. ==========
  11.  
  12. 1
  13. 2
  14. 2
  15. 1
  16.  
now trace_child(2,4)
please check once again!
thanks for kind response!
Atli's Avatar
Moderator
 
Join Date: Nov 2006
Location: Iceland
Posts: 3,751
#6: Aug 10 '08

re: PHP behaves strange when capturing 'return' value, how to over come?


What's your current code?

Also, if I may suggest and alternate solution to this problem.

Your current method of searching is somewhat wasteful.
Consider if you had one top-level menu, which had 100 child menus, each of which had a 100 child menus of their own.

If you were to try to match the root parent with the very last grandchild menu in that list, your search would have to go through every menu in the tree structure before it found a match.
Given our above data, that would take 9,999 queries!

My suggestion would be to search up from the child, looking for the parent, rather then your current method of searching down from the parent.

We don't usually build fully functional solutions for people, trying instead to help them create the solutions themselves.
But I found the best way to explain this properly would be to show you some code.

So, consider this.
Expand|Select|Wrap|Line Numbers
  1. function findParent($parent, $child) 
  2. {
  3.   // Set the starting point for our search
  4.   $current = $child;
  5.  
  6.   // Loop until the current menu is false.
  7.   // The root menu doesn't have a parent, so the parent of the root
  8.   // will be a null value (0), which will be evaluated as false, thus
  9.   // ending the loop.
  10.   while($current)
  11.   {
  12.     // Query for the parent of the current menu
  13.     $sql = "SELECT parent FROM menu WHERE child = $current";
  14.     $result = mysql_query($sql);
  15.     $row = mysql_fetch_assoc($result);
  16.  
  17.     // Replace the current menu with it's parent
  18.     // so the search can continue from this point
  19.     // in the next loop
  20.     $current = $row['parent'];
  21.  
  22.     // Check if the parent is the one we are looking for.
  23.     // If it is, the search is over and we return true
  24.     if($current == $parent) return true;
  25.   }
  26.  
  27.   // The loop has ended without finding the parent.
  28.   // The search failed. Return false.
  29.   return false;
  30. }
  31.  
This function would only ever have to execute an amount of queries less than or equal to the depth of the tree structure. Which in your case is only 2.
Newbie
 
Join Date: Aug 2008
Posts: 4
#7: Aug 11 '08

re: PHP behaves strange when capturing 'return' value, how to over come?


Quote:

Originally Posted by Atli

What's your current code?

Also, if I may suggest and alternate solution to this problem.

Your current method of searching is somewhat wasteful.
Consider if you had one top-level menu, which had 100 child menus, each of which had a 100 child menus of their own.

If you were to try to match the root parent with the very last grandchild menu in that list, your search would have to go through every menu in the tree structure before it found a match.
Given our above data, that would take 9,999 queries!

My suggestion would be to search up from the child, looking for the parent, rather then your current method of searching down from the parent.

We don't usually build fully functional solutions for people, trying instead to help them create the solutions themselves.
But I found the best way to explain this properly would be to show you some code.

So, consider this.

Expand|Select|Wrap|Line Numbers
  1. function findParent($parent, $child) 
  2. {
  3.   // Set the starting point for our search
  4.   $current = $child;
  5.  
  6.   // Loop until the current menu is false.
  7.   // The root menu doesn't have a parent, so the parent of the root
  8.   // will be a null value (0), which will be evaluated as false, thus
  9.   // ending the loop.
  10.   while($current)
  11.   {
  12.     // Query for the parent of the current menu
  13.     $sql = "SELECT parent FROM menu WHERE child = $current";
  14.     $result = mysql_query($sql);
  15.     $row = mysql_fetch_assoc($result);
  16.  
  17.     // Replace the current menu with it's parent
  18.     // so the search can continue from this point
  19.     // in the next loop
  20.     $current = $row['parent'];
  21.  
  22.     // Check if the parent is the one we are looking for.
  23.     // If it is, the search is over and we return true
  24.     if($current == $parent) return true;
  25.   }
  26.  
  27.   // The loop has ended without finding the parent.
  28.   // The search failed. Return false.
  29.   return false;
  30. }
  31.  
This function would only ever have to execute an amount of queries less than or equal to the depth of the tree structure. Which in your case is only 2.

Mr. Atli,
Thanks a ton man. It works fine now...
thanks
Reply