Magento – Get Active Filters in Observer Method

event-observerfilterlayered-navigationmagento-1.9

i want to check the currently applied layered navigation filters using an observer. When specific filter values are selected an additional layout handle should be added which adds a static block to the content.

For this i created a module which registers on the event controller_action_layout_load_before. In my observer method i call

  $appliedFilters = Mage::getSingleton('catalog/layer')->getState()->getFilters();

But somehow the filter array is always empty, no matter what i tried.

I thought allready of dispatching my own event and passing the filters as an argument, but that might be the dirty way.

Anyone has an idea why i can't access that data? I can access it in the template files.

Thanks a lot for your help!

config.xml:

<config>
    <modules>
        <My_CustomModule>
            <version>0.0.1</version>
        </My_CustomModule>
    </modules>
    <global>
        <models>
            <my_custommodule>
                <class>My_CustomModule_Model</class>
            </my_custommodule>
        </models>
    </global>
    <frontend>
        <events>
            <controller_action_layout_load_before>
                <observers>
                    <my_custommodule_observer>
                        <type>singleton</type>
                        <class>my_custommodule/observer</class>
                        <method>checkActiveFilters</method>
                    </my_custommodule_observer>
                </observers>
            </controller_action_layout_load_before>
        </events>
    </frontend>
</config>

Observer.php:

class My_CustomModule_Model_Observer 
{
    public function __construct()
    {
    }

    public function checkActiveFilters($observer)
    {
        $layout = $observer->getEvent()->getLayout();
        $appliedFilters = Mage::getSingleton('catalog/layer')->getState()->getFilters();
        foreach($appliedFilters as $filter) {
            Mage::log('Yay! appliedFilters is not empty!');
            $layout->getUpdate()->addHandle('FILTER_'.$filter->getFilter()->getRequestVar());
        }
    }
}

Best Answer

The event you are observing (controller_action_layout_load_before) is dispatched before layer filters are initialized. That's why you always get empty array when you call Mage::getSingleton('catalog/layer')->getState()->getFilters();.

In fact, I think there is no suitable single event in Magento for what you're trying to do (add custom layout update handle and get all applied filters).

I would like to suggest an alternative approach but I don't know if it will suit you.

Add following layout update via local.xml file:

<catalog_category_layered>
    <reference name="content">
        <block type="foo_bar/category" name="foo.bar.category.cmsblock" before="-"/>
    </reference>
</catalog_category_layered>

And create a block which extends from Mage_Cms_Block_Block class.

class Foo_Bar_Block_Category extends Mage_Cms_Block_Block
{
    protected function _toHtml()
    {
        $filters = array();
        $appliedFilters = Mage::getSingleton('catalog/layer')->getState()->getFilters();
        foreach($appliedFilters as $filter) {
            $filters[] = $filter->getFilter()->getRequestVar();
        }

        if (!empty($filters)) {
            $this->setBlockId(implode('_', $filters));
        }

        return parent::_toHtml();
    }
}

As you can see it's pretty simple. Line $this->setBlockId(implode('_', $filters)); sets the static block identifier and if the given block exists it will be loaded on your category pages.

Hope this helps.