I want my main menu to not include any categories that are empty. I've done this for the layered navigation very easily in the relevant phtml file by using
$_category->getProductCount()
However, for the navigation menu, I'm finding it impossible to do this as easily (I have seen the Prattski example but it does seem rather OTT).
The main menu seems to be built in Mage_Page_Block_Html_Topmenu.php
, specifically in the function _getHtml
. This gets all the children in the menu and if I try something like $child->getId()
, I get something like "category-node-36"
.
It doesn't seem like I'm too far from being able to use getProductCount()
and so test if it's more than zero.
Is it possible to do this? Can somebody point me to how?
If I can, I'll extend the class with my version.
To do this, go to:
app/code/core/Mage/Catalog/Block
Folder and copy Navigation.php and override it in your local package.Open Navigation.php of your package and paste below code in this file:
I hope my code will help you.
I finally cracked it although I'm far from convinced it's an optimum solution. Anyway, I'll described what I did here and hopefully somebody can make it more efficient. I'll give a blow-by-blow description as I was ufamiliar with quite a few areas. So apologies for the length.
As I said, in my case at least, the main menu is built via Topmenu.php in app/code/core/Mage/Page/Block/Html, specifically the method _getHtml. I very definitely don't want to modify a core file so I found out how to extend this method via a new module. (You can skip this bit if you're familiar with creating new modules.)
Configuring a new module
I needed to create a new module (I'll call it MYMOD below). As I'm overwriting the core magento page block, I had to create new folders: app/code/local/MYMOD/Page and in there two sub-folders, Block and etc (I believe they are case sensitive). And within Block another subfolder Html. You can see this is exactly mirroring the folder structure from app/code/core/Mage.
The etc folder holds the specification for the new module in a config.xml file. This is what mine looks like:
You can find out about the whys and wherefors of this elsewhere.
Unfortunately (in my opinion!), that's not all you have to do to specify a new module in Magento. You also have to create a file called "MYMOD_Page.xml" in app/etc/modules. This is just telling Magento about your module and where to look for it. Mine looks like this:
OK, sorry for the irrelevant instructions on modules but I do like self-contained blow-by-blow explanations.
Overwriting the method
I can now create a new file in my module with a subclass in which I can have methods (functions) that will be used instead of the core Magento ones. The file name has to be the same as the original file, Topmenu.php and it goes in app/code/local/MYMOD/Page/Block/Html.
Remember, the object oriented structure means that all of the functions in the original core version of Topmenu.php are available to me, I don't have to copy them in my new version (great for maintainability). My version of Topmenu.php only has to contain any new functions I might want (in this case I didn't need any) and redeclare any functions I want to overwite with my own version. In my case, I needed to modify two functions: _getHtml and _getMenuItemClasses.
_getHtml needs additional checks so any empty categories aren't included.
_getMenuItemClasses needs additional checks so that the class "parent" isn't added to categories whose children are empty.
Here's how I did it (with comments). I'm sure there are better ways but I'm still fairly new to Magento.
I hope this is clear. It does what I want (my store is small) but any suggestions for improvement welcome.
path: app/design/frontend/rwd/default/template/page/html/topmenu/renderer.phtml
Make this query (it is 0.0004 sec), under the foreach
($children as $child) {
It is very fast and secure way to control product count.