Problem space
I am trying to use an observer in magento to completely replace the entire layout for a given request based on the parameter in the request.
The problem I am 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 on the backend design tab). Since it does not use the layout I specified, it dies in PHP, trying to load templates that do not exist in the theme.
Any guidance is appreciated.
Note. I do not use the CMS page to test this concept, since they load their own templates, as indicated in the backend. I created a test product and use its product page. The test runs with the request of the following URL: http://mymagentosite.com/test-product?ajax=1
Possible problems
- Perhaps I am not listening to the correct event to completely replace the layout. The documentation is sparse, so I figured out based on other answers to the layout questions.
- The folder structure of the layout elements seems to me to be voodoo, since I find scattered opinions on this issue (for example, page.xml vs. local.xml)
Implementation
I created a module with an observer and a 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
<?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
<?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
<?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
<!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
<?xml version="1.0" encoding="UTF-8"?> <config> <modules> <MyCompany_MyModule> <active>true</active> <codePool>local</codePool> </MyCompany_MyModule> </modules> </config>