0

I'm trying to develop a hierarchical menu in my e-commerce website in which my categories are dynamically shown in order to add more categories without having to touch the code.

So I've organized my database like that, with 3 different ranks for my categories:

I got 3 different ranks:

  • First rank: Informatics [id=1] Accessories[2] vêtements[3] Hifi ..

  • Second rank: Hardware[parent_key=1][id=10] software[parent_key=1][id=11] Men[parent_key=3][id=30] ..

  • Third rank: motherboard[parent_key=10][id=100] processor[parent_key=10][id=101] Windows7[parent_key=11][id=110] Shoes[parent_key=30][id=300] ..

So you've understood that the "parent_key" refers to the parent id of my category abd for each category of rank 1 I got several rank 2 categories and so on ..

For now, I've hard-coded my menu in something like this:

<div id="main_menu">
  <ul id="nav">
    <li class="current"><a href="<?php echo base_url();?>">Home</a></li>
    <li><a href="#">High Tech</a>
      <ul>
        <li><a href="#">Informatique</a>
          <ul>
            <li><a href="#">Hardware</a></li>
            <li><a href="#">Ecrans</a></li>
            <li><a href="#">Clavier</a></li>
            <li><a href="#">Souris</a></li>
            <li><a href="#">Imprimantes</a></li>

          </ul>
        </li>
        <li><a href="#">TV</a>
          <ul>
            <li><a href="#">LCD</a></li>
            <li><a href="#">Plasma</a></li>
            <li><a href="#">3D</a></li>
          </ul>
        </li>
        <li><a href="#">Appareils Photos</a></li>
        <li><a href="#">GPS</a></li>
        <li><a href="#">Smartphones</a></li>
        <li><a href="#">Lecteur MP3</a></li>
        <li><a href="#">Hi-Fi</a>
          <ul>
            <li><a href="#">Amplificateurs</a></li>
            <li><a href="#">Enceintes</a></li>
            <li><a href="#">Cables</a></li>
            <li><a href="#">Autres</a></li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
  <br class="clear" />
</div>

I'm coding in MVC, and I don't know exactly how to build my model, my controller, and my view. I guess I'll have to do some if/else and foreach loop but I can't figure it out by myself.

If anyone wanna help to solve this problem, he is more than welcome :)

Adi Inbar
  • 12,097
  • 13
  • 56
  • 69
Miles M.
  • 4,089
  • 12
  • 62
  • 108

2 Answers2

1

Okay, thanks for all you post, but I found a way to deal with my problem, here my personal solution :

So I first begin by retrieving all the categories in a array : "allCategories"

Then, while I build the menu, with while loops and if conditions, I get what I want :

so we have, for each category

  • Category['cat_id'] which is the id of the category

  • Category['cat_title'] the name of the cat

  • Category['cat_order'] the rank of the category

  • Category['cat_parentkey'] the id of the parent of my categorie (Parent of motherboad: Hardware)

    $token1=TRUE;
    $token2=TRUE;
    
    foreach($allCategories as $Categories1){ //we are going to check all the cats :: on fait defiler toutes les catégories
    
        if($Categories1['cat_order']==1){ // if its rank 1 :: si le rang de la categorie est 1
            $key = $Categories1['cat_id']; // we save its ID
            echo '<li><a href="#">';
            echo $Categories1['cat_title'];
            echo '</a>'; // this is the loyaout to print the list, the /li comes further :: on fait la mise en page pour afficher la liste, le /li venant plus bas
    
            foreach($allCategories as $Categories2test){ // We gonna check if there is AT LEAST ONE categorie with an inferior rank, otherwise we do not print the <ul> which produce an ugly bar next to the menu :: on va tester si il existe AU MOINS UNE catégorie de rang inférieur, sinon on n'affiche pas de ul afin d'éviter une barre moche dans le menu
    
                if($Categories2test['cat_order']==2 AND $Categories2test['cat_parentkey']==$key AND $token1==TRUE){ // We do a test with a token which, once we do 1 loop inside, tell us there is at least one cat with an inferior rank :: on fait donc un test avec un token qui, une fois qu'on passe dedans 1 fois, nous dis qu'i'il y a donc au moins un rang inféireur
    
                    echo '<ul>'; // layout of our menu, is printed only if there is inferioir cats :: mise en forme du sous menu, ne s'affiche donc qu si il ya une categorie de ranf inferieur.
    
                        foreach ($allCategories as $Categories2){ // One again, we check all the cats :: on fait défiler les catégories
                            if($Categories2['cat_order']==2 AND $Categories2['cat_parentkey']==$key){ // If there is at least one of rank 2 so .... :: si il y en a 1 de rang 2 alors ...
                                $key2 = $Categories2['cat_id'];
                                echo '<li><a href="#">';
                                echo $Categories2['cat_title'];
                                echo '</a>';
    
                                foreach($allCategories as $Categories3test){
                                    if($Categories3test['cat_order']==3 AND $Categories3test['cat_parentkey']==$key2 AND $token2==TRUE){
                                        echo "<ul>";                                            foreach ($allCategories as $Categories3){
                                            if($Categories3['cat_order']==3 AND $Categories3['cat_parentkey']==$key2){
                                                $key3 = $Categories3['cat_id'];
                                                echo '<li><a href="#">';
                                                echo $Categories3['cat_title'];
                                                echo '</a>';
                                                echo "</li>";
                                            }
                                        }
    
                                        echo "</ul>";
                                        $token2=FALSE; 
                                    }
                                }
                            echo"</li>";
                            }
                        $token2=TRUE;
                        }
    
                    echo'</ul>';
                    $token1=FALSE; // We put our token to FALSE in order to avoid that loop for that particular rank1 category :: on met notre token à FALSE afin de ne plus refaire cette boucle pour cette catégorie de rang1
                }
            }
            echo "</li>"; 
        }
        $token1=TRUE; // We put the token to TRUE in order to do that loop again for the other rank 1 categorie :: on remet le token à 0 afin de repasser dans la boucle pour la catégorie de rang 1 suivante
    }
    

    ?>

Miles M.
  • 4,089
  • 12
  • 62
  • 108
0

Regarding the way to store data into a database (not the MVC part as i don't tend to use frameworks and i often build my own) i'd recommend this very good article:

http://www.sitepoint.com/hierarchical-data-database/

It talks about ways to store data into a database when you have hierarchical data. My prefered methods, depending on the output is the adjacency list or the traversal method. Up to you to choose the one you thinkg works best :)

Mathieu Dumoulin
  • 12,126
  • 7
  • 43
  • 71
  • Thanks for your help, However : Is that possible to combine hierarchical menu and MVC ? Thus, I don't understand, in the "MODIFIED PREORDER TREE TRAVERSAL" Methoads, How could I add more categories when you know that you have to give right and left numbers for each product ... And for the first one, I think It's incompatible with MVC isn't it ? – Miles M. Dec 30 '11 at 19:50
  • MVC is only a way to organise your code. It's not a fixed structure. Many frameworks exist out there that adopt the MVC pattern. I usually use a patern for models that correspond to a table mapper where one class provides static methods that will load the data and return activerecord based objects. The way you store data has nothing to do with the way you retrieve or represent the data. – Mathieu Dumoulin Dec 30 '11 at 19:55
  • Regarding the tree traversal. Adding an element in the middle of others is fairly simple, "UPDATE mytable SET rgt = rgt + 1 WHERE rgt >= xyz" then insert your new item with appropriate lft and rgt... – Mathieu Dumoulin Dec 30 '11 at 19:56
  • Wait i mistook that, it's not true at all, it's been a while i had to do this, it's both left and right where right is higher than a value. Anyway, any good traversal method will explain all that. I got it already coded and i don't look at it anymore :) – Mathieu Dumoulin Dec 30 '11 at 20:00