3

This question pops every time I create a new e-commerce site.

I have a horizontal main menu with Home, Products, Blog, etc... in it. I need to get the terms from my Product catalogue as the drop down menu underneath Products.

I use Taxonomy Menu to good effect elsewhere in the site, but I can't see any way of moving an entire Taxonomy Menu (or even a sub-set) to underneath a menu link in another menu.

My usual method is to hard-code a function into my theme (with appropriate caching of course), which builds up the sub-menu of terms. I then have to create another function to mimic the menu rendering functions, and inject the 'taxonomy menu' when my loop hits a certain menu link ID. Finally I use that function in place of the standard method of outputting menu links in my page template file.

Needless to say that's not a good method and it leaves me feeling dirty every time. I'd really prefer a more opaque method that keeps the menu in sync when terms in the vocabulary are changed.

It seems like this problem would have been solved over and over again, but my Google-fu is failing me.

Anyone got any good suggestions (that don't involve creating a View, which would be way too much overhead)?

I should also mention the lazy man in me is looking for a pre-built module to do this. It would be fairly trivial(ish) to implement the code on a case-by-case basis (see hampusn's comment below) but I'm hoping there's a generic module based solution available.

  • 1
    Have you looked at module_invoke_all('menu_rebuild', $menu, $changes) in combination with hook_taxonomy_term_insert($term)? I'm not sure when you want to rebuild the menu. – hampusn Sep 11 '12 at 14:11
  • @hampusn We'll call that plan B ;) I've added a bit more to the question. If you want to flesh that out a bit though feel free to put it in as answer; I can't say it'll be accepted but it's a good suggestion and I'm sure you'll get some credit for it – Clive Sep 11 '12 at 14:13
  • Hmm, my bad though. I can't find module_invoke_all('menu_rebuild' anywhere in the source so I'm not so sure it exists :). I might have gotten it from this issue. Your topic is interesting though. I'll dig some when I get home from work. – hampusn Sep 11 '12 at 14:17
2

I used this on a site a few months ago to essentially do the same thing:

function _foo_add_submenu ($menu_name, $vid, $plid)
{
  $vocabulary = taxonomy_vocabulary_load($vid);
  $tree = taxonomy_get_tree($vid);

  if (count($tree) > 0) foreach ($tree as $term) {
    $item = array(
      "link_path" => "taxonomy/term/{$term->tid}",
      "link_title" => $term->name,
      "menu_name" => "menu-menu",
      "plid" => $plid,
      "router_path" => "taxonomy/term/%",
    );

    $sql = "
      SELECT menu_links.mlid
      FROM {menu_links} menu_links
      WHERE menu_name = :menu_name AND plid = :plid AND link_path = :link_path
    ";

    $result = db_query($sql, array(
      ":menu_name" => $menu_name,
      ":plid" => $plid,
      ":link_path" => $item["link_path"],
    ));

    $record = $result->fetchObject();  

    if (isset($record->mlid) && $record->mlid > 0) $item["mlid"] = (int) $record->mlid;

    menu_link_save($item);
  }

  menu_cache_clear_all();
}

$menu_name is the menu to mess with, $vid is the vocabulary to build from, and $plid is the item to add to. When you run this, you will end up with a real menu in admin/structure/menu/manage/menu-whatever. You will need to add some additional housekeeping functions to handle adding terms, removing terms, etc, but they all involve similar functions and menu_link_save / menu_link_delete and menu_cache_clear or menu_cache_clear_all being called from the right taxonomy hook.

  • Note that I made some hand edits to "sanitize" this, so it may not run as-is. – mpdonadio Sep 11 '12 at 14:20
  • Thanks that looks very promising, I'll have a play around with it and let you know – Clive Sep 11 '12 at 14:35
  • Unfortunately this doesn't take term hierarchy into account, it just produces a flat list of everything in the vocab. I think it doesn't take deletions into account either but I haven't checked yet. Thanks for the start though – Clive Sep 11 '12 at 15:00
  • @Clive, correct, this just takes a flat vocabulary and turns it into a submenu. Consider it an example that shows the mechanics and how you work with plid and mlid from the {menu_links}. For a real tree, you just need to modify this to recurse top-down. I may have a more fleshed out version in my SVN, but I am not sure. – mpdonadio Sep 11 '12 at 16:23
  • I'm just working out that recursive function but it's a bi*ch, I'm finding it difficult to get the tree into a proper hierarchy so I can avoid race conditions with parent term creation/deletion. If you come across that code in your SVN at any point I'd be very grateful to see it – Clive Sep 11 '12 at 16:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.