Magento 1.8 – How to Update `catalog_category_view` Using Observer

event-observermagento-1.8update-handle

I am trying to set a root template to handler catalog_category_view through an observer. I know I can achieve it through layout update. But believe me I really need to dynamically set root template for handler. 🙂

The event that I am observing is controller_action_layout_generate_blocks_after and my observer is shown below

Observer.php

<?php

class Programmerrkt_Productperrow_Model_Observer

    public function setPrdouctListPage($observer)
    {
        $layout = $observer->getEvent()->getLayout();

        $layout_template = 'page/2columns-left';

        $layout->getUpdate()->addHandle('catalog_category_view')->addUpdate('<reference name="root"><action method="setTemplate"><template>'.$layout_template.'</template></action></reference>');

        return;
     }
}

Please note that, my event is observing my magento. Means config settings are correct.

But the code didn't work. It is not updating catalog_category_view handler. What is the possible cause for this.?

EDIT

When I output all layout, layout handler look like this

[catalog_category_view] => Mage_Core_Model_Layout_Element Object
(
    [reference] => Mage_Core_Model_Layout_Element Object
    (
       [@attributes] => Array
       (
           [name] => product_list
       )

       [action] => Mage_Core_Model_Layout_Element Object
       (
           [@attributes] => Array
           (
               [method] => addPriceBlockType
           )

           [type] => bundle
           [block] => bundle/catalog_product_price
           [template] => bundle/catalog/product/price.phtml
       )

    )

)

As you can see its not updating.

Share your thoughts please.

Best Answer

Try observing the event controller_action_layout_generate_blocks_after.
This is triggered after the blocks are generated. Just change the root template.

public function setPrdouctListPage($observer) {
    $action = $observer->getEvent()->getAction(); 
    $layout = $observer->getEvent()->getLayout();
    if ($action->getFullActionName() == 'catalog_category_view') {
        $root = $layout->getBlock('root');
        if ($root) {
            $root->setTemplate('page/2columns-left.phtml');
        }
    }
}

The down side of this is that the event is dispathced for every page. Even if your method does nothign for the rest of the pages it may impact (very little) the performance.

I think there is an other event you can use.
When viewing a category, the event catalog_controller_category_init_after is dispatched. that receives as parameter the current category.
You can use that and the category custom design settings to achieve what you need.

public function setPrdouctListPage($observer) {
    $category = $observer->getEvent()->getCategory(); 
    $category->setPageLayout('two_columns_left');
    //or if you want to set different page layouts depending on what is loaded `catalog_category_layered` or `catalog_category_default` you can do this. 

   if ($category->getIsAnchor()) {
       $category->setPageLayout('LAYOUT FOR anchor page here'); //this means `catalog_category_layered` is loaded
   }
   else {
        $category->setPageLayout('LAYOUT FOR non anchor page here'); //this means `catalog_category_default` is loaded
   }
}

This should act just like setting the 2columns-left layout from the backend.

As you can see I'm not questioning why you don't set this layout from the backend. I trust you have a reason. I just stated it here for future readers.

Related Topic