Jump to content

subforums again


doddsey_65

Recommended Posts

ive decided to go with a simpler version to the MPTT algorithm. I have 2 database table. Categories and forums.

 

categories

c_cid    c_name

  1          first category

 

forums

f_fid    c_id  p_id      f_name

  1        1      0            forum    --- this is a forum within category 1

  2        1      1      subforum    --- this is a subforum of forum within category 1

 

i am trying to display the name of any subforums under the forum name they belong to but with this code its only showing the subforums under the last forum displayed(which has no subforums). i think its something to do with the foreach loop as when i stick a var dump in there of the subforum list the list is only built when it gets to the bottom.

 

$s_list = $pids = $fids = array();
    $template->has_child = false;
    
    $query = $link->query("SELECT c.*, f.*
                        FROM ".TBL_PREFIX."categories c
                        LEFT JOIN ".TBL_PREFIX."forums f
                        ON (f.c_id = c.c_cid)
                        ORDER BY f.p_id ASC");
    $row = $query->fetchAll();
    
    foreach($row as $key => $value)
    {
        $forum_id = $row[$key]['f_fid'];
        $parent_id = $row[$key]['p_id'];
    
        for($i=0; $i<count($row); $i++)
        {
            $fids[] = $row[$i]['f_fid'];
            $pids[] = $row[$i]['p_id'];
        }
        
        if($row[$key]['p_id'] != 0)
        {
            $s_list[] = $row[$key]['f_name'];
            $template->is_child = true;
        }

        if($row[$key]['p_id'] == 0)
        {
            if(in_array($forum_id, $pids))
            {
                $template->has_child = true;
            }
            else
            {
                $template->has_child = false;
            }
            $template->f_name = $row[$key]['f_name'];
            $template->description = $row[$key]['f_description'];
            $template->children = implode(', ', $s_list);            
        }
        $template->fid = $row[$key]['f_fid'];
        $template->cat_name = $row[$key]['c_name'];    
        $template->render($template->template.'templates/forum_list_tpl.php');
    }    

 

anyone know why it will only display this list at the bottom and not under the correct forum?

Link to comment
Share on other sites

i think it would be better to do one table for forums.

when you are defining the id, cat id, forum id, child id, your node depth only goes down by three.

a better way would use one table, and have the parent decided from a parent_id field.

this way we can load the parents and children into different multi dem arrays.

here is an example:

<?php
$categories            = mysql_query("SELECT fid name, parent FROM forums");
while($row                = mysql_fetch_assoc($categories))
{
    if($row['parent']=='0')
    {
        //  these are root categories
        $cats[]             = $row;
    }
    else {

            //  these are all children, included sub-sub children, even sub-sub-sub children.
            $forums[$row['parent']][] = $row;
    }
}    
if(is_array($cats))
{
    foreach($cats as $cat)
    {
        if(is_array($forums[$cat['fid']]))
        {
            foreach($forums[$cat['fid']] as $forum)
            {

                // all of your forums children are loaded here.
                //  you can even loop the sub forums and find the 4th node children
                $forum['subforums']        = $forums[$forum['fid']];
                                
                //  Need to store this into the classes variable to be used globally.
                //  View will later be decided on if there is a forum id set.
                $this_forums[]                = $forum;
            }
        }
    }
    if(!empty($this_forums))
    {
        $nforums[]    = array($cat,$this_forums);
    }
    $this_forums        = array();
}
?>

 

your $nforums will be your main array that has everything organised there for a basic three node forum thee, this has your basic root forum category which contains forums underneath, those forums can also have children that are the same type of forum, just made normally for organisation. anyway, your $nforums array will look like this with a root cat, parent, and child.

<?php
['0'] => 
(
    ['0'] => 
    (
        ['fid'] = "1"
        ['name'] = "Root"
        ['parent'] = "0"
    )
    ['1'] =>
    (
        ['0'] =>
        (
            ['fid'] = "2"
            ['name'] = "Parent"
            ['parent'] =  "1"
            ['subforums'] =>
            (
                ['0'] => 
                (
                    ['fid'] = "3"
                    ['name'] = "Child"
                    ['parent'] = "2"
                )
            )
        )
    )
)
?>

 

you'll need your basic foreach loops to handle this code, if you decided to go this way and need any help let me know.

also, a demo of the actual forums that uses this can be found here.

Link to comment
Share on other sites

thanks for your reply. i have included your code but when i var dump $nforums it returns an empty array:

 

$cats = $forums = $nforums = array();
    $this_forums = array();
    
    $query = $link->query("SELECT f_fid, f_name, p_id FROM ".TBL_PREFIX."forums");
    while($row = $query->fetchAll())
    {
        if($row['p_id'] == 0)
        {
            //  these are root categories
            $cats[] = $row;
        }
        else 
        {
            //  these are all children, included sub-sub children, even sub-sub-sub children.
            $forums[$row['p_id']][] = $row;
        }
    }    
    if(is_array($cats))
    {
        foreach($cats as $cat)
        {
            if(is_array($forums[$cat['f_fid']]))
            {
                foreach($forums[$cat['f_fid']] as $forum)
                {
                    // all of your forums children are loaded here.
                    //  you can even loop the sub forums and find the 4th node children
                    $forum['subforums'] = $forums[$forum['fid']];
                                    
                    //  Need to store this into the classes variable to be used globally.
                    //  View will later be decided on if there is a forum id set.
                    $this_forums[]  = $forum;
                }
            }
        }
        if(!empty($this_forums))
        {
            $nforums[] = array($cat,$this_forums);
        }
    } 
    var_dump($nforums);

 

have i gone wrong somewhere?

 

Link to comment
Share on other sites

A dump of $cats:

 

array(1) { 
  [0]=> array(3) { 
      [0]=> array(6) { 
            ["f_fid"]=> string(1) "2" 
            [0]=> string(1) "2" 
            ["f_name"]=> string(10) "Discussion" 
            [1]=> string(10) "Discussion" 
            ["p_id"]=> string(1) "1" [2]=> string(1) "1" }
      [1]=> array(6) { 
            ["f_fid"]=> string(1) "1" 
            [0]=> string(1) "1" 
            ["f_name"]=> string(7) "General" 
            [1]=> string(7) "General" 
            ["p_id"]=> string(1) "0" 
            [2]=> string(1) "0" } 
      [2]=> array(6) { 
            ["f_fid"]=> string(1) "3" 
            [0]=> string(1) "3" 
            ["f_name"]=> string(9) "Sub Forum" 
            [1]=> string(9) "Sub Forum" 
            ["p_id"]=> string(1) "2" 
            [2]=> string(1) "2" } 
        } 
} 

 

but $forums returns empty

Link to comment
Share on other sites

something is off with the array, maybe it has to do with the $cats = $forums = $nforums = array(); ?

 

maybe it has to do with the query itself? it has these extra arrays that seem to be interferring with the rest of the code.

      [0]=> array(6) { 
            ["f_fid"]=> string(1) "2" 
            [0]=> string(1) "2" 
            ["f_name"]=> string(10) "Discussion" 
            [1]=> string(10) "Discussion" 
            ["p_id"]=> string(1) "1" [2]=> string(1) "1" }

which shoud look more like

      [0]=> array(6) { 
            ["f_fid"]=> string(1) "2" 
            ["f_name"]=> string(10) "Discussion" 
            ["p_id"]=> string(1) "1" 
}

 

so if you need to, check and see why the query returns that way, dump $row and see if that looks good, because you do have one parent and two forums so when $row['p_id'] doesn't equal 0, the $forums need to be filled, which it is not, so we need to debug some more.

Link to comment
Share on other sites

ok i assumed that i was using the wrong fetch method. I am using PDO for my connection and was using PDO::FETCH_ALL. Ive changed it to PDO::FETCH_ASSOC and the $row array appears normal(no added numeric keys). So now:

 

$cats:

 

array(1) { 
      [0]=> array(3) { 
          ["f_fid"]=> string(1) "1"
          ["f_name"]=> string(7) "General" 
          ["p_id"]=> string(1) "0" 
      } 
} 

 

$forums:

 

array(2) { 
[1]=> array(1) { 
      [0]=> array(3) { 
           ["f_fid"]=> string(1) "2" 
           ["f_name"]=> string(10) "Discussion" 
           ["p_id"]=> string(1) "1" } 
} 
[2]=> array(1) { 
       [0]=> array(3) { 
           ["f_fid"]=> string(1) "3" 
           ["f_name"]=> string(9) "Sub Forum" 
           ["p_id"]=> string(1) "2" } 
      } 
} 

 

but when i echo $nforums it shows that the forum "discussion" has no subforums. yet as you can see by the previous image it has 1 subforum

 

array(1) { 
      [0]=> array(2) { 
           [0]=> array(3) { 
                  ["f_fid"]=> string(1) "1" 
                  ["f_name"]=> string(7) "General" 
                  ["p_id"]=> string(1) "0" } 
           [1]=> array(1) { 
                  [0]=> array(4) { 
                       ["f_fid"]=> string(1) "2" 
                              ["f_name"]=> string(10) "Discussion" 
                              ["p_id"]=> string(1) "1" 
                              ["subforums"]=> NULL } } } } 

 

Link to comment
Share on other sites

You are correct, glad we got that fixed up.  Also of course the subforums are not being displayed, you need to fix your code:

 

$forum['subforums'] = $forums[$forum['fid']];

 

 

you need to make it

 

$forum['subforums'] = $forums[$forum['f_fid']];

 

Link to comment
Share on other sites

I'll be more than happy to help with that.

<?php
foreach($nforums as $cat)
{
    //  were going to have to imporant parts
    //  $cat[0] which is the root forum
    //  $cat[1] which are the sub forums

    echo '<h1>'.$cat[0]['name'].'</h1>';
    
    if (is_array($cat[1]))
    {
        foreach($cat[1] as $forum) 
        {
            echo '<h2>-'.$forum['name'].'</h2>';
            
            if(is_array($forum['subforums']))
            {
                foreach($forum['subforums'] as $sub)
                {
                    echo '<h2>--'.$sub['name'].'</h2>';
                }
            }
        }
    } 
}
?>

The code is fairly simple and self explanatory, i'm sure you won't have a problem adding extra information to the code and making it suit your needs.

 

Link to comment
Share on other sites

thanks for the advice and code so far, youve been great. However it only displays one forum( i have 2 now to test).

 

foreach($nforums as $cat)
    {    
        $template->f_c_name = $cat[0]['f_name'];
        if(is_array($cat[1]))
        {
            foreach($cat[1] as $forum)
            {
                $template->f_name = $forum['f_name'];
                
                if(is_array($forum['subforums']))
                {
                    foreach($forum['subforums'] as $child)
                    {
                        $template->subforums = $child['f_name'];
                    }
                }
            }
        }
        $template->render($template->template.'templates/forum_list_tpl.php');
    }

 

The render function basically sends the values defined using $template to a php tpl file which contains(simplified)

 

<h3><?php echo $this->f_name; ?></h3>

 

but like i said it only displays one forum(the last one).

Link to comment
Share on other sites

actually slight problem. I have a forum with a sunforum and a one without. For some reason it adds the sunforum of the first forum under the second one aswell.

 

foreach($nforums as $cat)
    {    
        $template->f_c_name = $cat[0]['f_name'];
        $template->is_cat = true;
        $template->render($template->template.'templates/forum_list_tpl.php');
        
        if(is_array($cat[1]))
        {
            foreach($cat[1] as $forum)
            {
                $template->f_name = $forum['f_name'];
                $template->is_cat = false;
                if(is_array($forum['subforums']))
                {
                    foreach($forum['subforums'] as $child)
                    {
                        $template->subforums = $child['f_name'];
                    }
                }
                $template->render($template->template.'templates/forum_list_tpl.php');
            }
        }
    }

Link to comment
Share on other sites

again this is a problem with the rendering, you need to mess around with where you place the template code a bit, i'm not sure how your tpl files are set up so i won't be too sure.  as long as your array doesn't display the sub forums for that specific forum then we know it's not an issue with the array which is our foundation of the script. so like i said, make sure the array is correct, if it is the problem is with the rendering so check your template parsing class and your tpl files.

Link to comment
Share on other sites

i fixed it, just added an else statement to the is_array($forums['subforums']).

 

also came across the problem of it only showing one subforum but i added $child['f_name'] to an array then imploded it.

 

Again thanks alot for your help!

Link to comment
Share on other sites

sorry but i have another problem. this time with the categories. All forums are just displayed under one category with the second category left empty.

 

i tired this but it hasnt worked. it displays about 6 categories all with a name which is a single letter(random letter).

 

if(is_array($cat[0]))
        {
            foreach($cat[0] as $parent)
            {
                $template->f_c_name = $parent['f_name'];
                $template->c_url_name = create_url($template->f_c_name);
                $template->render($template->template.'templates/forum_header_tpl.php');
            }
        }

 

forum_header_tpl.php:

 

</ul>
    <div class="category_header">
    <?php echo $this->f_c_name; ?>
    </div>
<ul class="forum_list">

Link to comment
Share on other sites

sorry but i have another problem. this time with the categories. All forums are just displayed under one category with the second category left empty.

 

i tired this but it hasnt worked. it displays about 6 categories all with a name which is a single letter(random letter).

 

if(is_array($cat[0]))
        {
            foreach($cat[0] as $parent)
            {
                $template->f_c_name = $parent['f_name'];
                $template->c_url_name = create_url($template->f_c_name);
                $template->render($template->template.'templates/forum_header_tpl.php');
            }
        }

 

forum_header_tpl.php:

 

</ul>
    <div class="category_header">
    <?php echo $this->f_c_name; ?>
    </div>
<ul class="forum_list">

 

change this to $cat[1]. $cat[1] are the subforums and their children, while $cat[0] are the root categories.

Link to comment
Share on other sites

i have the $cat[1] part in another section and removed the above code as it seemed to make things worse. Here is my code:

 

$cats = $forums = $cat_list = $cat_name = $nforums = $subforums = $this_forums = array();
    
    $query = $link->query("SELECT *
    FROM ".TBL_PREFIX."forums")or die(print_link_error());

    while($row = $query->fetch(PDO::FETCH_ASSOC))
    {
        if($row['p_id'] == 0)
        {
            //  these are root categories
            $cats[] = $row;
        }
        else 
        {
            //  these are all children, included sub-sub children, even sub-sub-sub children.
            $forums[$row['p_id']][] = $row;
        }
    }    
    if(is_array($cats))
    {
        foreach($cats as $cat)
        {
            if(is_array($forums[$cat['f_fid']]))
            {
                foreach($forums[$cat['f_fid']] as $forum)
                {
                    // all of your forums children are loaded here.
                    //  you can even loop the sub forums and find the 4th node children
                    $forum['subforums'] = $forums[$forum['f_fid']];
                                    
                    //  Need to store this into the classes variable to be used globally.
                    //  View will later be decided on if there is a forum id set.
                    $this_forums[]  = $forum;
                }
            }
        }
        if(!empty($this_forums))
        {
            $nforums[] = array($cat,$this_forums);
        }
    } 
    foreach($nforums as $cat)
    {    
        $template->f_c_name = $cat[0]['f_name'];
        $template->c_url_name = create_url($template->f_c_name);
        $template->is_cat = true;
        $template->render($template->template.'templates/forum_list_tpl.php');
    
        if(is_array($cat[1]))
        {
            foreach($cat[1] as $forum)
            {
                $template->is_cat = false;
                if(!empty($forum['f_last_post']))
                {    
                    $template->f_icon = $template->template.'icons/forum.png';
                    $template->f_last_post = $forum['f_last_post'];
                    $template->f_last_poster = profile_link($forum['f_last_poster']);
                    $template->f_last_post_time = asf_date($forum['f_last_post_time'],'full');
                }
                else
                {
                    $template->f_empty = true;
                    $template->no_posts = $lang->no_posts;
                    $template->no_posts_sub = $lang->be_first;
                    $template->f_icon = $template->template.'icons/forum_empty.png';
                }
                
                $template->f_name = $forum['f_name'];
                $template->f_url_name = create_url($template->f_name);
                
                $template->description = $forum['f_description'];
                
                if(is_array($forum['subforums']))
                {
                    foreach($forum['subforums'] as $child)
                    {
                        $template->s_url_name = create_url($child['f_name']);
                        $subforums[] = '<a href="category/'.$template->c_url_name.'/forum/'.$template->s_url_name.'">'.$child['f_name'].'</a>';
                        $template->subforums = implode(' ',$subforums);
                        unset($subforums);
                    }
                }
                else
                {
                    $template->subforums = null;
                }
                $template->render($template->template.'templates/forum_list_tpl.php');
            }
        }
    }

 

it only displays one cateogry(the last one) and displays all forums within that cat rather than in the cat they belong to.( i have 2 cats )

 

EDIT: i can supply you with a dump of my database table if that would help (project is open source anyway) or i can update github so you can see it there

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.