3

I have my layered navigation set up so that the user can filter by category, and this will filter the results on the page and stay on the category the filter was placed on e.g.

I have categories like so:

  • Balls
    • Rugby Balls
      • large
      • small
    • Football balls

If i am on rugby balls, in my layered navigation i have the option to filter for small or large rugby balls and the results are shown on the rugby balls page.

What i would like to do is instead of getting the results filtered, i would like, when the user wants to see whats in a sub category (large balls, small balls) they click on the link under the categories filter, but then actually get taken to the subcategory page instead of receiving filtered results.

Is there any way to do this?

5

Yes, very possible, and I do exactly the same for a client site.

First I created a new attribute for categories, to allow me to set that a category needs to use the normal link. This is done via a module.

The module structure:

app/code/local/ProxiBlue/AttributeUseNormalFilterLink/
app/code/local/ProxiBlue/AttributeUseNormalFilterLink/Model/Mysql4/
app/code/local/ProxiBlue/AttributeUseNormalFilterLink/etc
app/code/local/ProxiBlue/AttributeUseNormalFilterLink/sql/proxiblue_filterlink_setup

In Model/Mysql4 I have file Setup.php Contents:

class ProxiBlue_AttributeUseNormalFilterLink_Model_Mysql4_Setup extends Mage_Catalog_Model_Resource_Setup {

    private $_category_attributes = array(
        'use_normal_filter_link' => array(
            'label' => 'Use normal filter link in left navigation',
            'type' => 'int',
            'input' => 'select',
            'source' => 'eav/entity_attribute_source_boolean',
            'default' => '0',
            'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
            'visible' => true,
            'required' => false,
            'user_defined' => false,
            'visible_on_front' => true,
            'is_visible_on_front' =>true,
            'used_in_product_listing' => true,
        )
    );

    public function getDefaultEntities() {
        $entities = array();

        $default_attribute_options = array(
            'group' => 'General Information',
            'required' => false,
        );

        /* Build Catalog Attributes */
        $entities['catalog_category'] = array(
            'entity_model' => 'catalog/category',
            'attribute_model' => 'catalog/resource_eav_attribute',
            'table' => 'catalog/category',
            'additional_attribute_table' => 'catalog/eav_attribute',
            'entity_attribute_collection' => 'catalog/category_attribute_collection',
            'attributes' => array(),
        );
        foreach ($this->_category_attributes as $name => $options) {
            /* Override values provided by the defaults */
            $attribute_options = $default_attribute_options;
            foreach ($options as $k => $v) {
                $attribute_options[$k] = $v;
            }
            $entities['catalog_category']['attributes'][$name] = $attribute_options;
        }

        return $entities;
    }

}

in etc folder I have the config.xml contents:

<modules>
    <ProxiBlue_AttributeUseNormalFilterLink>
        <version>0.0.1</version>
    </ProxiBlue_AttributeUseNormalFilterLink>
</modules>

<global>
    <models>
        <proxiblue_attributeusenormalfilterlink>
            <class>ProxiBlue_AttributeUseNormalFilterLink_Model</class>
        </proxiblue_attributeusenormalfilterlink>
    </models>
    <resources>
        <proxiblue_filterlink_setup>
            <setup>
                <module>ProxiBlue_AttributeUseNormalFilterLink</module>
                <class>ProxiBlue_AttributeUseNormalFilterLink_Model_Mysql4_Setup</class>
            </setup>
        </proxiblue_filterlink_setup>
    </resources>
</global>

and in the sql fiolder I have the install script : mysql4-install-0.0.1.php contents:

$installer = $this;
$installer->startSetup();
$installer->installEntities();
$installer->endSetup();

Now you can adjust the filter template to use this attribute, and any category can be set to display the actual category link, and not work as a filter.

Copy the template catalog/layer/filter.phtml to your custtom theme folder, then adjust as follows: (note this has some other customization, so pull the bits you need)

<?php $category = false; ?>
<?php if ($this instanceof Mage_Catalog_Block_Layer_Filter_Category): ?>
<?php $category = Mage::registry('current_category'); ?>
    <?php if ($category): ?>
    <h2>
    <a class='level-top' href="<?php $category->getUrl(); ?>"><?php echo $category->getName(); ?></a>
    </h2>
    <?php endif; ?>
<?php endif; ?>
<ol>
    <?php foreach ($this->getItems() as $_item): ?>
    <li>
        <?php if ($_item->getCount() > 0): ?>
        <?php
            $link = $_item->getUrl();
            if(is_object($category) && !$category->getUseNormalFilterLink()){
                $filter = $_item->getFilter();
                if($filter instanceof Mage_Catalog_Model_Layer_Filter_Category) {
                    $linkCategory = mage::getModel('catalog/category')->load($_item->getValue());
                    if($linkCategory->getId()){
                        $link = $linkCategory->getUrl();
                    }
                }
            }
        ?>
        <a href="<?php echo $this->urlEscape($link) ?>"><?php echo $_item->getLabel() ?></a>
        <?php else: echo $_item->getLabel() ?>
        <?php endif; ?>
        <?php //echo $_item->getCount() ?>
    </li>
    <?php endforeach ?>
</ol>
  • 1
    Nice solution. one comment though. Instead of this if(get_class($this) == "Mage_Catalog_Block_Layer_Filter_Category") I think it's better to use if ($this instanceof Mage_Catalog_Block_Layer_Filter_Category), in case the block class Mage_Catalog_Block_Layer_Filter_Category is rewritten by an other module – Marius Oct 17 '13 at 10:14
  • Good point, not sure why I did it like that. Will adjust my code, and answer – ProxiBlue Oct 17 '13 at 12:27
0

It's possible you can use this code for magento 2.

For magento 2, we have the same function in vendor\magento\module-catalog\Model\Layer\Filter\Item.php we have getUrl() function.

the orignal code:

public function getUrl()
    {
        $query = [
            $this->getFilter()->getRequestVar() => $this->getValue(),
            // exclude current page from urls
            $this->_htmlPagerBlock->getPageVarName() => null,
        ];
        return $this->_url->getUrl('*/*/*', ['_current' => true, '_use_rewrite' => true, '_query' => $query]);
    }

and then the custom code to solve the issue:

public function getUrl()
    {
        if($this->getFilter()->getRequestVar() == "cat"){
            $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
            $category_url = $objectManager->create('Magento\Catalog\Model\Category')->load($this->getValue())->getUrl();
            $return = $category_url;
            $request = $this->_url->getUrl('*/*/*', array('_current'=>true, '_use_rewrite'=>true));
            if(strpos($request,'?') !== false ){
                $query_string = substr($request,strpos($request,'?'));
            }
            else{
                $query_string = '';
            }
            if(!empty($query_string)){
                $return .= $query_string;
            }
            return $return;
        }
        else{
            $query = array(
                $this->getFilter()->getRequestVar()=>$this->getValue(),
                $this->_htmlPagerBlock->getPageVarName() => null // exclude current page from urls
            );

            return $this->_url->getUrl('*/*/*', array('_current'=>true, '_use_rewrite'=>true, '_query'=>$query));
        }
    }

It's working only category section. It's working fine in my case.

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.