2

[No Extension pitches please (if I want to be spammed, I'll use the magento forum :D)]

I can see this/similar has been asked before (and elsewhere).
In most cases, I see people 'recommending' extensions - yet this should be doable with some code tweaks ... so I thought I'd ask.

Attribute value Name in the URL, not the ID.

The normal filtered URL looks like this;
/[attribute_name]=[attribute_id]
/colour=4

I (and many others) would like to see;
/[attribute_name]=[attribute_value]
/colour=red

To do this, I need to alter (a "local" version of); /app/code/[code|local]/Mage/Catalog/Model/Layer/Filter/Item.phtml

The default code is;

public function getUrl()
{
    $query = array(
        $this->getFilter()->getRequestVar()=>$this->getValue(),
        Mage::getBlockSingleton('page/html_pager')->getPageVarName() => null // exclude current page from urls
    );
    return Mage::getUrl('*/*/*', array('_current'=>true, '_use_rewrite'=>true, '_query'=>$query));
}

Yet any changes I make here seem to result in the filters not loading properly.

I've been trying this (and variants);

public function getUrl()
{
    if($this->getFilter()->getRequestVar() == 'attribute_1_name'){
    // do nothing
    }
    $query = array(
        $this->getFilter()->getRequestVar()=>$this->getValue(),
        Mage::getBlockSingleton('page/html_pager')->getPageVarName() => null // exclude current page from urls
    );
    return Mage::getUrl('*/*/*', array('_current'=>true, '_use_rewrite'=>true, '_query'=>$query));
}

(Even simply inserting an if (or if/else) condition results in the attributes not loading - nor the footer!)

Now I assume that I need to do the following;
1) Check for a value in the URL
2) Fetch a collection of filterable attributes
3) Look through that list for a match to the URL value
4) get that values ID
5) Pass that ID to magento in the return data.

But I've little clue on what api/funcs exist in magento to achieve this.

Further - I'm not sure if doing this will also update the links in the filter ... it would be pointless to look in the URL for specific attribute values, if the links are pointing to URLs with only IDs ... so will I need to also update whatever file handles the URL creation?

Thank you very much for any assistance you can give.

.
[No Extension pitches please (if I want to be spammed, I'll use the magento forum :D)]

2
  • Not sure if the "anti-spam" request is putting people off, if there's a general lack of answer-ers, or if it's just a plain hard question??? Commented Nov 27, 2013 at 12:18
  • Worth noting in Enterprise it uses labels for attribute based filters by default
    – PanPipes
    Commented Dec 5, 2015 at 20:23

1 Answer 1

2

In addition to changing the URL which is being rendered, you'll need to rewrite Mage_Catalog_Model_Layer_Filter_Attribute::apply():

/**
 * Apply attribute option filter to product collection
 *
 * @param   Zend_Controller_Request_Abstract $request
 * @param   Varien_Object $filterBlock
 * @return  Mage_Catalog_Model_Layer_Filter_Attribute
 */
public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
{
    $filter = $request->getParam($this->_requestVar);
    if (is_array($filter)) {
        return $this;
    }
    $text = $this->_getOptionText($filter);
    if ($filter && strlen($text)) {
        $this->_getResource()->applyFilterToCollection($this, $filter);
        $this->getLayer()->getState()->addFilter($this->_createItem($text, $filter));
        $this->_items = array();
    }
    return $this;
}

$this->_getResource()->applyFilterToCollection($this, $filter) is where the ID is passed in. Your change needs to map the option text to the ID prior to this. Something along the lines of the following will get you going:

public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
{
    $filter = $request->getParam($this->_requestVar);
    if (is_array($filter)) {
        return $this;
    }
    $filter = $this->getAttributeModel()->getSource()->getOptionId($filter);
    $text = $this->_getOptionText($filter);
    if ($filter && strlen($text)) {
        $this->_getResource()->applyFilterToCollection($this, $filter);
        $this->getLayer()->getState()->addFilter($this->_createItem($text, $filter));
        $this->_items = array();
    }
    return $this;
}

I'm a bit concerned as to what effect this will have on caching, etc. but at least this will head you down the road to a solution.

1
  • Thank you very much @benmarks - I'd given up on getting an answer! I will give this a try later today and see how it goes. Commented Dec 7, 2013 at 11:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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