Layered navigation, but not quite

Recently I got a chance to rewrite Magento’s layered navigation standard functionality. The request was very specific as the client wanted to keep all of the “filters” visible all the time. For example if you wish to filter your results by Color (let’s say you have yellow, green, red, blue and magenta) products are filtered but the layered navigation displays all filters. This way a costumer can re-filter the products in current category without the need to return to the category view.

Files that are used for layered navigation are situated in app/design/frontend/base/default/template/catalog/layer/ folder. File used for layered navigation is view.phtml – it shows us all of the filters when we click on a category. File used for active state is state.phtml – when we click on one of the filters it is responsible for the results – so we’re gonna edit this one. So copy the state.phtml from base to your package or theme.

Since we’re going to need url path of current category add this code before “currently” div block

<?php$obj=new Mage_Catalog_Block_Navigation();?><?php$_current_category=$obj->getCurrentCategory()->getUrlPath();?> //getting url path of current category
<?php$subs=$obj->getCurrentCategory()->getAllChildren(true);?> //getting ids of subcategories of current category

Now we’re going to edit “currently” div, i renamed my to state, since it doesn’t show just current filter state anymore. Experienced Magento developers will notice that not all of the code is programmed Magento-way, but when I programmed it (Magento CE 1.4.2. ) Magento still didn’t have needed functions. I guess they didn’t expect from someone to use layered navigation this way. So, here we go!

The next thing that needs to be done is to extract the information from attribute model and assemble links. Each of attribute options ($attroptions) contains attribute value (id) and attribute label.

<?phpforeach($attroptionsas$attr):?> // get value and label of each attribute
<?php$count=0;?><?phpif($attr["value"]!=""):?><?php$val=$attr["value"]?><?php$collection->addFieldToFilter(array(array('attribute'=>'themes','gt'=>10)))?> // collection of attribute values and labels for all values
//greater then 10 (in this case attribute values range was 18-39)
<?php$proddata=$collection->getData()?> // get product data for all attribute values
<?phpif($attr["label"]!=$this->stripTags($_filter->getLabel())):?> // make a nice looking label
<?phpforeach($proddataas$prod):?><?phpif($prod["type_id"]=="configurable"):?> // in this store all products were configurable
<?php$split=split(",",$prod["color"]);?> // get the attribute values that correspond with one product (a product may have more
// then one attribute value and they're separated by commas that's why we split the string with "," as deliminator)

Even thought you set your attribute to Filterable(with results) you still have to count the products in order to output only attribute values that have product count >0 .

<?phpforeach($splitas$color):?> //check out how many products have the same attribute value
<?phpif($color==$attr["value"]):?><?php$count++;?><?phpendif;?><?phpendforeach;?><?phpendif;?><?phpendforeach;?><?phpif($count>0):?> // check if any product has that attribute value
<li><a href="<?phpecho$this->getUrl('').$_current_category?>?color=<?phpecho$attr["value"]?>" ><?phpecho$attr["label"];?></a></li> // if not currently active filter make a link
<?phpendif;?><?phpelse:?>
<li class="current"> <?phpecho$this->stripTags($_filter->getLabel());?></li> // if currently active filter write out the label
<?phpendif;?><?phpendif;?><?phpendforeach;?><?phpendforeach;?> // ending the first for loop (foreach($filters as $filter))
</ol>
</dd>
</dl>
<a class="all" style="float:right;" href="<?phpecho$this->getClearUrl()?>">All</a> // show all products, return from current state back to category view
</div>
<?phpendif;?>

And that’s it. Our task of keeping the filters visible all the time is finished 🙂 . Now where ever you go using layered navigation you’ll be able to simply re-filter the products in current category without the need to go back to category view. And for the end a brief warning – some code here isn’t programmed Magento-way, because needed functions weren’t available. I hope I explained the problem and solution well enough :).
Cheers!

You’re a damn fraud. If anyone reads this article carefully, they’ll realize the code is very specific and wouldn’t have worked unless you mirrored the author’s exact store configuration, even if you tried using it on Magento 1.4.

It’s hack code at best. Just another fluff article to try and legitimize their company and for others to advertise their crappy plugins. Cancerous.

Hi! The thing you’ve described is rather popular now. Actually we needed the same for our electronics shop and were searching for different solutions. First we wanted to program it by ourselves, but then took a look at the appropriate extensions on Magento Connect. In the end we purchased Improved Navigation module from Amasty, and it’s really the best sollution for layered navigation. You can try it if you want http://amasty.com/improved-navigation.html

I think that’s because, like me, you also have the category filter. So you need to bypass this. Note, apparel_color is a custom attribute, and definitely will be different in your case. Instead of checking for attribute option code, which is a number, I have set it to check for the option label: apparel_color_value.

I think there is a bug in getting the product collections from the subcategories.

<?php foreach($subs as $cat_id): ?>

and later the $collection here {code] addFieldToFilter(array(array(‘attribute’=>’themes’,’gt’=>10)))?>

will only reference the last collection.
Also, the code will run slowly for large collection of products.
I come up with a different approach by getting only the distinct colors from the collection [code]$collection->addAttributeToSelect('apparel_color_value')
->getSelect()->group('color');

Your email address will not be published. Required fields are marked *

Comment

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.