Displaying root categories in top menu

Anybody could help to generate root categories for top menu dynamically? When I add a category to top menu through admin the category is not displayed as selected if any of its subcategories or products are selected.

Why this code is not working in top_menu.tpl:

{foreach from=$categories item=category key=cat_key name=“categories”}

{if $category.level == “0”}


It’s not picking up any categories …

Could you provide more info? Some statements seem a little contradictory. I.e.


When I add a category to top menu through admin the category is not displayed as selected




if any of its subcategories or products are selected


Selected where? In the Top Menu you either select a single or all categories.

When you click on a subcategory in the categories box or any submenu the root category for that subcategory if it is in the top menu is no longer displayed as highlighted (off). Also when a user clicks on any product he does not know which category or subcategory the product belongs to (unless he looks for breadcrumbs which are small and intended mostly for search engines anyway). If dynamic categories menu box is enabled the cat tree collapses each time a product page is displyed instead of highlighting the subcategory for that product. This makes navigation more difficult and confusing.

On my current website (v1.3) the top meny displays only root categories. Instead of adding them manually through admin they are generated automatically using the code similar to this in top_menu.tpl:

{foreach from=$categories item=category key=cat_key name=“categories”}

{if $category.level == “0”}



Whenever a product details page is displayed the root category for that product is highlighted in the top menu and the subcategory name is highlighted in the caterories box tree (dynamic menu).

this code is not working in v2.

What do you have in your “Activate tab menu for” input box in your Top Menu for Categories?

Mine lists: “categories.catalog, categories.view, products.search, products.view”.

Whenever I’m on a category or product page the tab is highlighted correctly.

I think I’m still missunderstanding what your problem is.

Say you have three root categories: books, computers, dvd. If you add them all to the top menu using admin and use views you are referring to, the program would not recognize which of those categories a certain product belongs to. I already tried it. It highlights only the first category you select and then gets stuck there. Try it. Add three categories to the top menu and then click on various featured products in your home page. Will the top menu highlight the correct category for each product you select? If you have dynamic menu enabled through blocks for you categories box will it highlight the subcategory for that product in the expanded category tree or will the tree collapse?

Check deepdiscount.com and see how their top categories work for different products.

I hope I made it a little clearer.

I don’t use featured products so can’t duplicate here. But if the “view” is in the list of “Activate tab menu for” then it will highlight the tab. I.e. if ‘featured products’ resolves to a dispatch=products.view then the tab will be highlighted. If it resolves to some other controller/mode then simply list that controller.mode in the “Activate tab menu for” input box.

If you have three categories: books, computers, dvd in your top menu, and you have product view enabled, the program has absolutely no clue which category the product belongs to. You click on books in the top menu - books get highlighted. If later on you start viewing other products - computers, dvds or apparel you will still get books category highlighted in the top menu which is wrong and confusing… If the first one you clicked was computers tab in the top menu - you will get computers tab highlighted even if you are viewing books or underwear.

My main question is though: why the piece of code I mentioned earlier does not work in the top_menu.tpl? Looks like it does not call categories function at all. This v2 is a lot harder to modify for simple things like this one…

This is what I get if I activate tab menu for product view in computer category. Please see image and note the product → category relationship.

Or for books category I activate category view tab.

7-28-2009 12-30-18 AM.jpg

7-28-2009 12-29-03 AM.jpg

This is what I am trying to get


This is a very good idea. i am very evil that this isnt a standard, because it is very user friendly.

Imagery is a little too small for these old eyes…

I’m going to guess that $category.level is not being passed as part of the $category array.

What does adding a {debug} ahead of the foreach tell you?

After I changed the code in the top_menu.tpl it still shows the previous ctaegory (the one clicked on before I replaced the piece of code (computers), I even tried to clean the blocks cache, but may be another cache shoud be cleaned too):

To make the job easier I found the php code that controls the categories box:


function fn_get_categories($params = array(), $lang_code = CART_LANGUAGE)


$default_params = array (

‘category_id’ => 0,

‘visible’ => false,

[COLOR=“Red”]‘current_category_id’ => 0,[/COLOR]

‘simple’ => true,

‘plain’ => false,

‘sort_order’ => ‘desc’,

‘limit’ => 0,

‘sort_by’ => ‘position’,

‘item_ids’ => ‘’,

‘group_by_level’ => true,

‘get_images’ => false


This value should not be 0, it should be the current product main category id. I cannot find the param to pass. I tried $category_id, $product_data[‘main_category’].

Any ideas?


Got it! Though this solution is to show expanded category tree when viewing product details page (see the third image) and not for the top menu. Now I can certainly find a workaround for the top menu categories by just rewriting the code in the hook.

function fn_get_categories($params = array(), $lang_code = CART_LANGUAGE)


[COLOR=“Red”]$product_id = $_REQUEST[‘product_id’];

$category_id = db_get_field(“SELECT ?:products_categories.category_id FROM ?:products_categories LEFT JOIN ?:categories ON ?:categories.category_id=?:products_categories.category_id WHERE ?:products_categories.product_id=‘$product_id’”); [/COLOR]

$default_params = array (

‘category_id’ => 0,

‘visible’ => false,

[COLOR=“Red”]‘current_category_id’ => $category_id, [/COLOR]

‘simple’ => true,

In categories_tree.tpl:

class=“{if $category.category_id == $smarty.request.category_id [COLOR=“Red”]|| $product.main_category == $category.category_id[/COLOR]}subcategories-link-active{else}subcategories-link{/if}”>

That code is only returned if there are no categories defined.

To clear the whole page cache simply remove the directory (and all its files and subdirectories) of var/compiled.

This will cause all the templates you access to be re-cached.

I wouldn’t be messing with fn_get_categories()… It is controlled by the parameters passed to it which vary widely depending on what area of the system is asking for category information… You might solve this specific issue, but may impact other operations that are not obvious at this point.

Just my two cents.

Remember I tested it only with dynamic categories menu. My old Website (v1.3)is structured like this so it will probably work for me.

I’m trying to do something similar. I want to put the category list in the side nav and the footer. However, when I put the foreach command in the footer, nothing happens, though it works in the side nav. Anybody able to explain this? I’m new to smarty, so there might be something I am missing.

This code works in menu_items.tpl, but not in other templates:

{assign var=“foreach_name” value=“cats_$cid”}

{foreach from=$items item=“category” name=$foreach_name}

{if $category.subcategories}

    {include file="views/categories/components/menu_items.tpl" items=$category.subcategories separated=true submenu=true cid=$category.category_id}




Anybody able to explain this?


I would assume that the “categories” template variable is not refrenced correctly (the foreach for “items”). Hence “items” does not have a value and the foreach does not execute.

sorry, that’s a red herring. That code works. The code that doesn’t work is this:

[QUOTE]{assign var=“foreach_name” value=“cats_$cid”}

{foreach from=$items item=“category” name=$foreach_name}



So it doesn't have anything to do with templates.

It has something to do with context, definitely, but I don't know what the rules are that allow me to use a foreach in one place and not in another