Welcome Guest, Not a member yet? Register   Sign In
Help with recursion
#1

[eluser]TheFuzzy0ne[/eluser]
Hi everyone. I'm having some trouble with recursion, and I was wondering if anyone could help, or offer a better solution.

Here's an array representing the tree structure of my forums:

Code:
Array
(
    [id] => 45
    [title] => Forums
    [children] => Array
        (
            [0] => Array
                (
                    [id] => 46
                    [title] => Forum 1
                    [children] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 47
                                    [title] => SubForum 1
                                )
                            [1] => Array
                                (
                                    [id] => 48
                                    [title] => SubForum 2
                                )
                        )
                )
            [1] => Array
                (
                    [id] => 49
                    [title] => Forum 2
                )
        )
)

From that array, I'd like to get a subforums array that would look something like this:

Code:
Array
(
    [45] => Array
        (
            [0] => Array
                (
                    [id] => 46
                    [title] => Forum 1
                )
            [1] => Array
                (
                    [id] => 49
                    [title] => Forum 2
                )
        )
    [46] => Array
        (
            [0] => Array
                (
                    [id] => 47
                    [title] => SubForum 1
                )

            [1] => Array
                (
                    [id] => 48
                    [title] => SubForum 2
                )
        )
    [47] => Array
        (
        )
    [48] => Array
        (
        )

    [49] => Array
        (
        )
)

So basically, I want to be able to grab a forum's subforums from the array, using the forum ID as the key. Hopefully this makes sense.

Here's the exported array for anyone who is interested in having a bash at getting this to work.

Code:
$tree = array
(
    'id' => 45,
    'title' => 'Forums',
    'children' => array
    (
        0 => array
        (
            'id' => 46,
            'title' => 'Forum 1',
            'children' => array
            (
                0 => array
                (
                    'id' => 47,
                    'title' => 'SubForum 1'
                ),
                1 => Array
                (
                    'id' => 48,
                    'title' => 'SubForum 2'
                )
            )
        ),
        1 => array
        (
            'id' => 49,
            'title' => 'Forum 2'
        )
    )
);

If it comes to it, I could always add a parent_id field to the database, but that may cause problems and unnecessary database queries when I move the forums around.

Many thanks in advance.
#2

[eluser]wiredesignz[/eluser]
This is the format of a static function I have used previously to recursively build a tree menu.
Code:
class tree
{
    static function recurse($arr) {
        
        foreach ($arr as $key => $value) {
            
            if (is_array($value)) { //branch contains an array
    
                $out .= self::recurse($value);
            
            } else {
                
                if ($key == 0) {
        
                    $out = //begin a new branch
                
                } else {
    
                   $out .= //manage branch items

                }
            }
        }
        return $out;
    }
}
#3

[eluser]gtech[/eluser]
here is my solution I have tested

Code:
function ptree() {
      $tree = array
      (
          'id' => 45,
          'title' => 'Forums',
          'children' => array
          (
              0 => array
              (
                  'id' => 46,
                  'title' => 'Forum 1',
                  'children' => array
                  (
                      0 => array
                      (
                          'id' => 47,
                          'title' => 'SubForum 1'
                      ),
                      1 => Array
                      (
                          'id' => 48,
                          'title' => 'SubForum 2'
                      )
                  )
              ),
              1 => array
              (
                  'id' => 49,
                  'title' => 'Forum 2'
              )
          )
      );
      // put tree in array so recursion can work without having to write
      // a special case for the root.
      $atree = array();
      $atree[] = $tree;
      // now lets generate the new tree
      $newtree = array();
      $newtree = $this->checkchildren($newtree,$atree);
      print_r($newtree);
  }
  function checkchildren($newarray,$checkarray) {
      foreach ($checkarray as $key=>$val) {
        $newarray[$checkarray[$key]['id']] = array();
        $newarray[$checkarray[$key]['id']]['title'] = $val['title'];
        if (array_key_exists('children',$checkarray[$key])) {
          // call same function to check children
          $newarray = $this->checkchildren($newarray,$checkarray[$key]['children']);
          foreach ($checkarray[$key]['children'] as $ckey=>$cval) {
            $newarray[$checkarray[$key]['id']][] = array('id' => $cval['id'],
                                                         'title' => $cval['title']);
          }
        }

      }
      return $newarray;
  }


result:

Code:
Array
(
    [45] => Array
        (
            [title] => Forums
            [0] => Array
                (
                    [id] => 46
                    [title] => Forum 1
                )

            [1] => Array
                (
                    [id] => 49
                    [title] => Forum 2
                )

        )

    [46] => Array
        (
            [title] => Forum 1
            [0] => Array
                (
                    [id] => 47
                    [title] => SubForum 1
                )

            [1] => Array
                (
                    [id] => 48
                    [title] => SubForum 2
                )

        )

    [47] => Array
        (
            [title] => SubForum 1
        )

    [48] => Array
        (
            [title] => SubForum 2
        )

    [49] => Array
        (
            [title] => Forum 2
        )

)
#4

[eluser]TheFuzzy0ne[/eluser]
Thanks a lot guys. I will be checking them out later on tonight.
#5

[eluser]umefarooq[/eluser]
here is some solution for tree

http://www.phpbits.info/php-tutorial/rec...on-in-php/

have look on it hope it will work.
#6

[eluser]TheFuzzy0ne[/eluser]
umefarooq, unfortunately that method requires each forum category to have a parent_id field, which is what I'm trying to avoid.

However, I've spent several hours trying to figure out what was going wrong, and I think I've finally figured it out.

Here's the tree. It's pretty much the same format as before, with the only change being that the IDs are now different (although the structure is still almost identical), and the tree itself is in an array, which I think is the key to this whole thing working.

Code:
Array
(
    [0] => Array
        (
            [id] => 120
            [title] => Forums
            [children] => Array
                (
                    [0] => Array
                        (
                            [id] => 121
                            [title] => Forum 1
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 122
                                            [title] => SubForum 1
                                        )
                                    [1] => Array
                                        (
                                            [id] => 123
                                            [title] => SubForum 2
                                        )
                                )
                        )
                    [1] => Array
                        (
                            [id] => 124
                            [title] => Forum 2
                        )
                )
        )
)

Here's my function:
Code:
function get_subforums_array($tree, $parent_id=NULL)
{
    $subforums = array();
        
    foreach($tree as $node)
    {    
        $children = (isset($node['children'])) ? $node['children'] : FALSE;
        
        unset($node['children']);
        
        if ( ! isset($subforums[$node['id']]))
        {
            $subforums[$node['id']] = array();
        }
        
        if ($parent_id)
        {
            $subforums[$parent_id][] = $node;
        }
        
        if ($children)
        {
            $sf = get_subforums_array($children, $node['id']);
            
            foreach ($sf as $key => $val)
            {
                if ( ! isset($subforums[$key]))
                {
                    $subforums[$key] = $val;
                }
            }
            
            $subforums += $sf;
        }
    }
    
    return $subforums;
}

Granted, it certainly doesn't look like several hours worth of code, but this is the result:

Code:
Array
(
    [120] => Array
        (
            [0] => Array
                (
                    [id] => 121
                    [title] => Forum 1
                )
            [1] => Array
                (
                    [id] => 124
                    [title] => Forum 2
                )
        )
    [121] => Array
        (
            [0] => Array
                (
                    [id] => 122
                    [title] => SubForum 1
                )
            [1] => Array
                (
                    [id] => 123
                    [title] => SubForum 2
                )
        )
    [122] => Array
        (
        )
    [123] => Array
        (
        )
    [124] => Array
        (
        )
)

So now I can grab a list of subforums for any forum, and only make a single database query for the the lot.

Thanks to all who tried to help. I really appreciate it.
#7

[eluser]wiredesignz[/eluser]
Code:
function get_subforums_array($tree=array(), $parent_id=NULL)
Otherwise foreach will generate an error if $tree = NULL
#8

[eluser]TheFuzzy0ne[/eluser]
That's exactly what I want it to do, however, I should have just omitted the default value completely. The reason the default was set to NULL, is because that function is now part of my model, which optionally accepts the initial tree array, and if $tree is NULL, the the model automatically grabs the tree from the database.

For the standalone function, if the function hasn't been passed a tree, the developer will immediately see the error and be able to ensure that a tree is passed to it. $tree is not meant to be an optional variable, whereas $parent_id is. Likewise, an error will be triggered if the $tree is not an array. In a sense, it behaves like any other PHP function if you don't give it the right number of arguments, or feed it data of the wrong type.

Which would you rather do:

a) See an error that tells you you've not provided enough arguments, prompting you to recheck what you're passing in, or
b) Find that FALSE is returned for some strange reason, and spend some time scratching your head, and perhaps even screaming at your monitor?

Hopefully that makes sense to you. I know it's not how everyone operates, but it's how me and my lollerskates roll. Big Grin
#9

[eluser]wiredesignz[/eluser]
Sure generate an error but do not kill the script. Teach those Lollerskates to code properly.
EDIT:
Actually no, I take that back. It doesn't really matter. You code as you feel you should.




Theme © iAndrew 2016 - Forum software by © MyBB