Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Sep 2002
    Location
    667 - neighbour of the beast!
    Posts
    1,113
    Rep Power
    139

    Displaying menus with parents


    Hi there,

    I've got a problem with is burning my brain at the moment. Basically it goes like this...

    I've got a mySQL table called menudata which will store the structure for my menu

    menu_id (Autoincrement, index)
    menu_name
    menu_parent_id


    And the data in that table will be something like this.....

    Code:
    1     Reviews     0
    2     Links     0
    3     Gallery     0
    2     Games     1
    3     Hardware     1
    4     Other     1
    5     Games     2
    6     Manufacturers     2
    7     Game Pics     3
    8     Clan Pics     3
    9     Other     3
    10     Medal of Honour     7
    11     Halflife     7
    12     UT2003     7
    Now what I want to do is extract this data from my sql database and display the structure as it's meant to be, based on the parent/child structure, like this....

    Code:
    Reviews
        - Games
        - Hardware
        - Other
    Links
        - Games
        - Manufacturers
    Gallery
        - Game Pics
            - Medal of Honour
            - Halflife
            - Other
        - Clan Pics
        - Other

    So basically, ideas on the most efficient way to do this (without a heap of accesses to mySQL). I figure it's got something to do with arrays most likely cos there won't be too many menu categories - but I've been thinking about this for 2 days now and my head hurts.

    Any pointers would be great.

    Many thanks,
    JT
  2. #2
  3. phpkid ~~~~~~ :o)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Nov 2000
    Location
    NJ, USA
    Posts
    2,534
    Rep Power
    21
    Check this

    PHP Code:
    <?php

    $query 
    "select * from menu";

    $result mysql_query($query);

    $max_parent 1;
    while(
    $arr mysql_fetch_array($result))
    {
        
    //If there is no parent for the item.
        
    if ($arr['menu_parent_id'] == 0)
        {
            
    $menu_arr[$arr['menu_id']][] = $arr['menu_name'];
            
    $max_parent++;
        }
        else
        {
            
    $menu_arr[$arr['menu_parent_id']][] = $arr['menu_name'];
        }
    }

    print_r($menu_arr); //This will help you in understanding how the items are arranged.

    //Now you can access menu like
    for($i=1;$i<$max_parent;$i++)
    {
        
    $child_arr $menu_arr[$i];
        
    $parent_name $menu_arr[$i][0];
        foreach(
    $child_arr as $key => $child)
        {
            if(
    $key !=0)
                print 
    "Parent : $parent_name - Child : $child <br>";

        }
    }

    ?>
    Can you make out code, OR I need to explain??

    JD
  4. #3
  5. Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Sep 2002
    Location
    667 - neighbour of the beast!
    Posts
    1,113
    Rep Power
    139
    I think I can understand it. Gonna try to work it in to my grand-plan right now. Stand-by for silly questions!!!

    Many thanks for the reply.
  6. #4
  7. Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Sep 2002
    Location
    667 - neighbour of the beast!
    Posts
    1,113
    Rep Power
    139
    I almost got it!! (although don't fully understand some of the code - my brain doesn't work fast enough!)

    I wrote this into my own example and the display was as follows....

    Code:
    Array ( [1] => Array ( [0] => MENU A [1] => MENU A-A [2] => MENU A-B [3] => MENU A-C ) [2] => Array ( [0] => MENU B [1] => MENU B-A [2] => MENU B-B [3] => MENU B-C ) [3] => Array ( [0] => MENU C [1] => MENU C-A [2] => MENU C-B [3] => MENU C-C ) [4] => Array ( [0] => MENU A-A-A [1] => MENU A-A-B [2] => MENU A-A-C ) ) 
    
    Parent : MENU A - Child : MENU A-A 
    Parent : MENU A - Child : MENU A-B 
    Parent : MENU A - Child : MENU A-C 
    Parent : MENU B - Child : MENU B-A 
    Parent : MENU B - Child : MENU B-B 
    Parent : MENU B - Child : MENU B-C 
    Parent : MENU C - Child : MENU C-A 
    Parent : MENU C - Child : MENU C-B 
    Parent : MENU C - Child : MENU C-C
    Which looks right - except there was one more sub-menu under MENU A-A which didn't display? Not sure if it's something I've done or not, but the code is unaltered.

    Apart from that, you achieved more in 5 minutes than I did in 2 days! lol....
  8. #5
  9. Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Sep 2002
    Location
    667 - neighbour of the beast!
    Posts
    1,113
    Rep Power
    139
    Or a better way of viewing it (sorry bout the wide format - I thought it auto-wrapped!!)....

    This is my raw data.....

    Code:
    1 | MENU A | 0
    2 | MENU B | 0
    3 | MENU C | 0
    4 | MENU A-A | 1
    5 | MENU A-B | 1
    6 | MENU A-C | 1
    7 | MENU B-A | 2
    8 | MENU B-B | 2
    9 | MENU B-C | 2
    10 | MENU C-A | 3
    11 | MENU C-B | 3
    12 | MENU C-C | 3
    13 | MENU A-A-A | 4
    14 | MENU A-A-B | 4
    15 | MENU A-A-C | 4

    And this is how it displays at the moment...


    Code:
    MENU A
    - MENU A-A
    - MENU A-B
    - MENU A-C
    MENU B
    - MENU B-A
    - MENU B-B
    - MENU B-C
    MENU C
    - MENU C-A
    - MENU C-B
    - MENU C-C

    But as you see above from the data, it should look like this....

    Code:
    MENU A
     - MENU A-A
        - MENU A-A-A
        - MENU A-A-B
        - MENU A-A-C
     - MENU A-B
     - MENU A-C
    MENU B
     - MENU B-A
     - MENU B-B
     - MENU B-C
    MENU C
     - MENU C-A
     - MENU C-B
     - MENU C-C

    Any ideas?
  10. #6
  11. phpkid ~~~~~~ :o)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Nov 2000
    Location
    NJ, USA
    Posts
    2,534
    Rep Power
    21
    My code wasn't geared to handle 3 levels!

    Hm... I will have to think. I will repost once I get a better solution.

    JD
    Last edited by jdk; June 6th, 2003 at 12:49 AM.
  12. #7
  13. No Profile Picture
    Devshed Novice (500 - 999 posts)

    Join Date
    Feb 2003
    Location
    Indonesia
    Posts
    905
    Rep Power
    23
    PHP Code:
    <?
    $connmy 
    mysql_connect("localhost""user""password");

    function 
    showTree($pid) {
        
    $query1 "select * from menu where menuparent = $pid";
        
    $reslt1 mysql_db_query("dbname"$query1);
        if (
    mysql_num_rows($reslt1) > 0) {
            while (
    $hasil1 mysql_fetch_array($reslt1)) {
                
    $npid $hasil1['menuid'];
                echo 
    "<ul>";
                    echo 
    "<li>".$hasil1['menuid']." - ".$hasil1['menuname']."</li>";
                
    showTree($npid);
            }
        }
        echo 
    "</ul>";
    }

    showTree(0);
    ?>
    should handle any level
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2001
    Posts
    286
    Rep Power
    18
    You need a resursive alogrithm something like this should work.

    PHP Code:
    function make_tree($topId)
    {
      
    $query="
      SELECT menu_id,menu_id
      FROM menudata
      WHERE parent_id=
    $topId");
      
    $results=mysql_query($query);
      while(
    $row=mysql_fetch_array($results))
      {
        
    $menu[$topId][$row['menu_id']]=$row['menudata'];
        
    array_merge($menu,make_tree($row['menu_id']);
      }
      return 
    $menu

    Or the one above, sorry beaten to the punch.
  16. #9
  17. phpkid ~~~~~~ :o)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Nov 2000
    Location
    NJ, USA
    Posts
    2,534
    Rep Power
    21
    I guess he doesn't want to make multiple queries.

    Otherwise this will surely work.

    Actually if you will have around 50 rows for menu items, querying 3 times (for 3 levels of menu) will not be BIG deal, but I just wanted to solve the problem in single query just for fun!

    JD
  18. #10
  19. PHP n00b
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2002
    Posts
    46
    Rep Power
    17
    yes very fun...

    i think i have something working it seems to do at least four levels but i think it can hadle a infinate number. The code may be difficult to understand i just wrote it to see if i can solve the challange (well not realy i wrote it yesturday to make a explorer like navigation system for a CMS i am builing for a website) but the first function orders them into levels and the second joins them up with there parents. You may ned to modify the query at the top but becasue there is only 1 that should be all you need to do. The code is fast for what it does so speed isnt much of a problem realy (i tested the code on a tree that contains around 90 entrys)

    btw i dont suggest you just copy and paste the code i would if i was you "try" and work out whats going on!

    I have not added any comments in yet as i was in a hurry yesturday so i did not have much time to do that. and there is mostlikly 1 or 2 things that arnt supposed to be there as i have not optimized it yet!

    this is the sorting code

    PHP Code:
    $result1 mysql_query("select * from ".$details["prefix"]."_topics ORDER BY t_sub_id;");
    while(
    $topicsmake1=mysql_fetch_array($result1))
    {

        if (empty(
    $topicsmake1["t_sub_id"]))
        {
            
    $topicsmake1["t_sub_id"] = "0";
        }
        if (
    $topicsmake1["t_id"] >= 10)
        {
            
    $topicsmake1["t_id"] = $topicsmake1["t_id"][0] . "-" $topicsmake1["t_id"][1];
        }
        if (
    $topicsmake1["t_sub_id"] >= 10)
        {
            
    $topicsmake1["t_sub_id"] = $topicsmake1["t_sub_id"][0] . "-" $topicsmake1["t_sub_id"][1];
        }
        
    $t_new_id[$count] = $topicsmake1["t_sub_id"]. "." $topicsmake1["t_id"] . "|.|" $topicsmake1["t_sub_id"]. "," $topicsmake1["t_id"] . "," $topicsmake1["t_name"];
       
    $count++;
    }

    unset (
    $count);
    function 
    builder ($t_new_id){
        
    sort ($t_new_id);
        
    $i 0;
        foreach (
    $t_new_id as $t_no_array)
        {
            
    $slice explode("|.|"$t_no_array);
            
    $t_array explode(","$slice[1]);
            
    $t_array_size count($t_new_id);
            while (
    $count $t_array_size)
            {
                
    $t_array_order explode("|.|"$t_new_id[$count]);
                
    $t_array_order1 explode(","$t_array_order[1]);
                if((
    $t_array[0] == $t_array_order1[1]) && ($t_array[0] != "0"))
                {
                    
    $new_string $t_array_order[0] . "." $t_array[1] . "|.|" "0" "," $t_array[1] . "," $t_array[2] . "," $t_array[3];
                    
    $t_new_id[$i] = $new_string;
                    
    $reloop "1";
                }
                if ((
    $array_first[0] != 0) && ($zero[$lastnum] == $array_first[0]))
                {
                    
    $new_string $t_array_order[0] . "." $t_new_id[$i];
                    
    $t_new_id[$i] = $new_string;
                }
                
    $count++;
            }
            unset(
    $count);
           
    $i++;
        }
        
    $output = array ($reloop$t_new_id);
        return 
    $output;
    }

    function 
    buildercheck($t_new_id){
        
    sort ($t_new_id);
        
    $i 0;
        foreach (
    $t_new_id as $t_no_array)
        {
            
    $slice explode("|.|"$t_no_array);
            
    $t_array explode(","$slice[1]);
            
    $t_array_size count($t_new_id);
            
    $count 0;
            while (
    $count $t_array_size)
            {
                
    $t_array_order explode("|.|"$t_new_id[$count]);
                
    $t_array_order1 explode(","$t_array_order[1]);
                
    $zero explode("."$t_array_order[0]);
                
    $array_first explode("."$slice[0]);
                
    $lastnum count($zero);
                
    $lastnum $lastnum 1;
                if ((
    $array_first[0] != 0) && ($zero[$lastnum] == $array_first[0]))
                {
                    
    $new_string $t_array_order[0] . "><" $t_new_id[$i];
                    
    $new_string str_replace("." $zero[$lastnum] . "><""."$new_string);
                    
    $t_new_id[$i] = $new_string;
                }
                
    $count++;
            }
            
    $i++;
        }
        return 
    $t_new_id;
    }

    $output[0]= "1";
    while (
    $output[0] == "1")
    {
        
    $output builder($t_new_id);
        
    $t_new_id $output[1];
    }

    $t_new_id buildercheck($t_new_id);
    rsort ($t_new_id); 
    and then the display code

    PHP Code:
    echo "<table cellspacing=\"0\" cellpadding=\"0\">\n";
    echo 
    "<tr>\n";
    echo 
    "<td><table cellspacing=\"0\" cellpadding=\"0\"><tr><td colspan=\"80\" style=\"cursor:hand;\">
    <img src=\"../../templates/images/folder.gif\" />Root</td></tr></table>"
    ;
    echo 
    "</tr>\n";
    foreach (
    $t_new_id as $t_no_array)
    {
        
    $slice explode("|.|"$t_no_array);
        
    $t_array explode(","$slice[1]);
        
    $top explode("."$slice[0]);
        
    $loop count($top);
        
    $loop $loop -1;
        if (
    strlen($t_array[2]) > 22)
        {
            
    $t_array[2] = substr($t_array[2], 022) . "...";
        }
        echo 
    "<tr>\n<td>\n<table cellspacing=\"0\" cellpadding=\"0\">\n<tr>\n";
        while (
    $z $loop)
        {
            
    $junc $loop-1;
            if (
    $z == $junc)
            {
                echo 
    "<td background=\"../../templates/images/dashline_horz.gif\"><img src=\"../../templates/images/dashline_junc.gif\" /></td>";
            }
            else
            {
                echo 
    "<td><img src=\"../../templates/images/dashline.gif\" /></td>";
            }
            
    $z++;
        }
        unset(
    $z);
        echo 
    "<td colspan=\"50\" style=\"cursor:hand;\"><img src=\"../../templates/images/folder.gif\" />" $t_array[2] . "</td>";
        echo 
    "\n</tr></table></td></tr>";
    }
    echo 
    "</table>"
    lots of code so hope you never fell asleep
    Last edited by stewis; June 6th, 2003 at 06:05 AM.
  20. #11
  21. Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Sep 2002
    Location
    667 - neighbour of the beast!
    Posts
    1,113
    Rep Power
    139
    Thanks for the replies folks. I've been away all weekend, but will take a look at them all tomorrow at work.

  22. #12
  23. Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Sep 2002
    Location
    667 - neighbour of the beast!
    Posts
    1,113
    Rep Power
    139
    These are really clever solutions folks. nice work! I'm still working on making a 'one-query' solution, but agree it's gonna have to be some sort of recursive function. Was thinking about it when I was away at the weekend (sad but true!!)

    I suppose that I could read it into an array beforehand and just use that as my data source. My next objective is to make it so that I can collapse the menus (i.e.. not show the collapsed menu items, but show their parents).
  24. #13
  25. PHP n00b
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2002
    Posts
    46
    Rep Power
    17
    *pstt* my code only used 1 query but ordered them with more than one for each
  26. #14
  27. Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Sep 2002
    Location
    667 - neighbour of the beast!
    Posts
    1,113
    Rep Power
    139
    Lol... yeah, sorry m8 - I did notice that. Was speaking from a personal point of view. I'm trying to write my own based around the ideas from these posts.

    You all did great work - all unique in their own ways. I'll likely end up writing something which is a mixture of both of them. Actually, the next thing I was looking at was storing a breadcrumb trail of menus accessed - so I can calculate whats been opened in the tree.

    All good stuff... keep it coming!
  28. #15
  29. PHP n00b
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2002
    Posts
    46
    Rep Power
    17
    ahh k
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo