Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override entire magento layout from observer

Problem Space

I'm trying to use an observer in magento to completely replace the entire layout for a given request based on a parameter in the request.

The issue I'm facing is that Magento is still trying to load a different root block template than the one I specified in my Observer (specifically "frontend/base/default/template/page/1column.phtml" for product pages which is the default root block template used by the template configured in the design tab of the backend). Because it isn't using the layout I specified, it dies in PHP trying to load templates that don't exist in the theme.

Any guidance is appreciated.

Note: I am not using a CMS page to test this concept since they load their own templates as specified in the backend. I created a test product and am using its product page. The test is made by requesting the following URL: http://mymagentosite.com/test-product?ajax=1

Possible Issues

  • I may not be listening to the right event to completely replace the layout. Documentation is sparse so I guessed based on other Stack Overflow responses to layout questions.
  • Folder structure of layout elements seems like voodoo to me since I find disparate opinions on the subject (e.g. page.xml vs. local.xml)

Implementation

I've created a module with an observer and a very minimal layout as follows:

Module Folder Structure

app
├── code
│   └── local
│       └── MyCompany
│           └── MyModule
│               ├── etc
│               │   └── config.xml
│               └── Model
│                   └── Observer.php
├── design
│   └── frontend
│       └── myTheme
│           └── default
│               ├── layout
│               │   └── local.xml
│               └── template
│                   └── test.phtml
└── etc
    └── modules
        └── MyCompany_MyModule.xml

config.xml

<!-- language: lang-xml -->
<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <MyCompany_MyModule>
            <version>0.1.0.0</version>
        </MyCompany_MyModule>
    </modules>
    <global>
        <events>
            <controller_action_layout_generate_xml_before>
                <observers>
                    <myCompany_myModule_model_observer>
                        <type>singleton</type>
                        <class>MyCompany_MyModule_Model_Observer</class>
                        <method>changeRequestLayout</method>
                    </myCompany_myModule_model_observer>
                </observers>
            </controller_action_layout_generate_xml_before>
        </events>
    </global>
</config>

Observer.php

<!-- language: lang-php -->
<?php

class MyCompany_MyModule_Model_Observer
{
    public function changeRequestLayout($observer)
    {
        if ($observer->getAction()->getRequest()->isAjax()) {
            Mage::getDesign()->setArea('frontend')->setPackageName('myTheme')->setTheme('default');
        }
    }
}

local.xml

<!-- language: lang-xml -->
<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.1.0.0">
    <default>
        <block type="page/html" name="root" output="toHtml" template="test.phtml" />
    </default>
</layout>

test.phtml

<!-- language: lang-html -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Testing, testing...1...2...3...</title>
    <style type="text/css">
        body {
            background-color:#f00;
        }
    </style>
</head>
<body>
    <h1>This is a test of the Magento layout system.  This is only a test.  If this were not a test, real content would follow.</h1>
</body>
</html>

MyCompany_MyModule.xml

<!-- language: lang-xml -->
<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <MyCompany_MyModule>
            <active>true</active>
            <codePool>local</codePool>
        </MyCompany_MyModule>
    </modules>
</config>
like image 980
Coren Avatar asked Jul 03 '13 22:07

Coren


People also ask

How do I override a Magento template?

More specifically, in Magento 2, any module's or parent theme's layout, template, or web can be overridden with ease just by placing it in <theme_dir>/<Vendor>_<Module>/path/to/file . For instance, for the Magento_Theme module, you can place your template in <theme_dir>/Magento_Theme/templates/html/header.


1 Answers

This is a working solution i built that definitely does the job of switching the design package/theme via controller_front_init_before event.

Of course you could check some request params inside changeConfigNode() method with Mage::app()->getRequest()->getParam('switch') and just append the request param switch/1 to trigger the changes.

   <global>
    <events>
        <controller_front_init_before>
            <observers>
                <cartware_change_the_node>
                     <class>cartware_guest2customer/observer</class>
                     <method>changeConfigNode</method>
                </cartware_change_the_node>
            </observers>
        </controller_front_init_before>               
    </events>
   </global>

And the observer method:

public function changeConfigNode(){

    /** left for testing
    Mage::log( Mage::app()->getConfig()->getXmlString());
            **/

    Mage::app()->getConfig()->setNode('stores/default/design/package/name', 'enterprise');
    Mage::app()->getConfig()->setNode('stores/default/design/package/theme', 'enterprise');
    Mage::app()->getConfig()->setNode('stores/default/design/package/default_theme', 'enterprise');
    Mage::app()->getConfig()->setNode('stores/default/design/theme/default', 'enterprise');
    Mage::app()->getConfig()->setNode('stores/default/design/theme/layout', 'enterprise');
    Mage::app()->getConfig()->setNode('stores/default/design/theme/template', 'enterprise');



}

Its without additional checks but it might help you! Good luck!

like image 50
Michael Leiss Avatar answered Nov 15 '22 08:11

Michael Leiss