Is there a better way?

Hello,

I am building a dynamic menu. What I am wanting to use is twitter boostrap, which is I am remembering correctly uses a ordered list for top menu items and then an ordered list inside that for sub menu items.

I currently have that syntax printing out as a simple list, but I am just wondering if there is a better way to do so?

This is what I currently have:

[php]

    <?php for($i=0 ; $i < count($menu); $i++) { echo '
  • '.($menu[$i]['Category']['name']. '
  • '); echo '
      '; for($j=0; $j < count($subcategories); $j++) { if($subcategories[$j]['Subcategory']['category_id']== $menu[$i]['Category']['id']) { echo '
    • '.$subcategories[$j]['Subcategory']['name'] .'
    • '; } } echo '
    '; } ?>
[/php]

It simply goes through my menu array and print out the name of the top level item, and then it prints out the submenu item. This uses an ID for the top level and a category_id to know which item belong to which top level category.

The issue I am having with how this is implemented is that it will literate through the entire submenu on each pass. This means if I have a large menu it will have to literate through a lot of data that won’t be printed in that pass. So is there a better way of doing this while keeping it short, sweet and most of all dynamically created?

Thanks,
Valandor

A.K.A.
Anthony

Data normalization is a pretty good step forward. Building a tree is even better.

[php]function build_tree($subcategories) {
$result = [];
foreach ($subcategories as $k => $v) {
if (!empty($result[$v[‘Subcategory’][‘category_id’]])) $result[ $v[‘Subcategory’][‘category_id’] ] = array();
$result[ $v[‘Subcategory’][‘category_id’] ] = $k;
}
return $result;
};[/php]

This gives you a very handy normalization function. This takes a bunch of disorganized data and builds a very simple key => array(children) pattern out of it. From it, all you need to do is traverse down. The key in question is the category_id, which you have as your menu category ID.
Run the function on your subcats before doing the menu, and just store its output as a lookup table.

Best of all, this also allows you to make it recursive, provided that your data is already normalized - i.e. that ID is unique. In the future, however, you may want to consider the fact that a subcategory is just a category… and build an associative relation between categories to make your life easier (and lighten the load on your DB server if you’re pulling from a DB to do this).

Thank you for this information. A lot will be ran through the categories and subcategories on my site. It will be used to populate the menu, allow members to sign up under a category and if they choose a sub category, and I’m also looking into creating the ability to choose services offered for each category/sub-category with the use of check-boxes. All of this of course will go into making it to where people can search through the site and find what they are looking for rather quickly. There is a lot of associations, so any way I can take strain off of the server or db server is appreciated advice.

Thank you much sebrenauld! I added some karma to for you.

If you use them that much, I would recommend changing your table structure to something like this:

table: categories

[code]id UNSIGNED INTEGER
name VARCHAR(255)
Any other meta info you’d like

Indices: id PRIMARY AUTO_INCREMENT[/code]

table: category_association

[code]id UNSIGNED INTEGER
parent_id UNSIGNED INTEGER
category_id UNSIGNED INTEGER

Indices: id PRIMARY AUTO_INCREMENT
parent_id INDEX
category_id INDEX[/code]

The reason for this table structure is pretty simple: one simple WHERE call on an indexed column is far better than an entire table lookup. This allows promiscuity in your menu - you only load what you want. The row size is small enough that your entire can stay as a temporary table in memory without trouble, which will make subsequent lookups faster than the initial (MySQL will move all your data to memory in this particular case due to the very small footprint of the tables).

This also allows a couple of benefits:

  • A category can now be a child of multiple categories natively
  • A category is now normalized. It is a unique reference across your tables
  • You can now find descendents of a category without having to load the entire categories table
  • Building a menu can now be done using a recursive function
  • Results can now be easily cached

A lookup for descendents on a category is as simple as looking in the associative table (category_association) for rows where parent_id is the id of the parent category you are trying to find. From there, find the IDs, and load them from the other table.
If you want to get even faster lookups, cache the results from the categories table (Not the associative). This means that the only queries hitting your MySQL server will be association links, in which every row is exactly 12 bytes in size. That’s tiny.

Thank you so much for this. I will start building and testing this all out now. I am using cakephp right now for my application, and it’s been a while sense I’ve worked on a large project. I was learning PHP a while back ago, and to give you an idea how long ago people who in a craze over how register_globals where the future of PHP development.

I can still do a lot of basics and create things that are secure and pretty easy to manage, but a lot has changed in how things are done and why they are done one way over another. I also have a lot of issues planning out my database structure which is important for any database driven project. I’m hoping this will become easier in time, but if you know of any good references to learn how to properly plan out database structures that would really nice. I stay away from php academy as much as possible but I read a lot of tutorials on mySQL, along with tutorials on PHP.

The information provided is more than valuable to me and I hope one day to be able to repay the favor.

Depending on the communities you spend time on, this is still a craze. I have never seen someone say anything positive about register_globals, ever, personally (and I’ve been coding for 15 years). :wink:

I can still do a lot of basics and create things that are secure and pretty easy to manage, but a lot has changed in how things are done and why they are done one way over another. I also have a lot of issues planning out my database structure which is important for any database driven project. I'm hoping this will become easier in time, but if you know of any good references to learn how to properly plan out database structures that would really nice. I stay away from php academy as much as possible but I read a lot of tutorials on mySQL, along with tutorials on PHP.

Indeed, many things have changed. SQL itself has gone leaps and bounds, MySQL in particular, along with design rules and methodologies for databases. If you are interested in things like what I’ve said, you will not find this in tutorials online (let’s face it, tutorials are “Hey! Print ‘Hello world’! That’s it, you know PHP!”). Depending on your level of knowledge of MySQL, I would recommend the following two books:

The second one is worth a bit more description, as the warning will most likely not sell it. This book has every single thing that MySQL does and can do under the hood, including an in-depth breakdown of how the various storage engines operate. It also has sections on clustering, sharding, replication, query profiling and optimization, and a whole bunch of other stuff you may be interested in.
It does NOT have a single line of PHP in it, and has roughly 1500 pages. Which is a tremendous amount of information on MySQL. And yes, normalization is covered.

All this info is only worth it if you apply it. The advantage with these methods is, since every element on your database ends up with a unique, canonical ID, you can very, very easily build models up for your data. This makes data retrieval dead-easy, and most PHP frameworks support this natively (all extensions of Symfony, basically). It’s also the backbone of the MVC development approach.

Thank you for the books, I will be picking them once I am able to. Even if I have to go in and redo what I have to take some strain off of the server it will be worth the time. It’s nice to have experienced scripters here to help out with questions and who are willing to share knowledge, and I thank you for this. You don’t have to be here helping, but you are. I will be here helping when I really get a hang of things.

Thank you my friend.

Sponsor our Newsletter | Privacy Policy | Terms of Service