Redefine the entire mannequin from the observer

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

 <!-- 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> 
+6
source share
2 answers

Real problem

Magento's layered XML layout system is a source of confusion when doing what should be a trivial use case.

Since the basic / standard XML layout is combined with any layout that I specify, I must not only redefine the root layout, but also all other derived layouts defined in the /default/page.xml database. This is not practical since Magento defines a large number of custom layouts depending on the type of page the client is viewing.

My decision

The cleanest solution is to create symbolic links in the template / page directory to point to my test.phtml file for all of the following layouts. This ensures that Magento will only use my layout template.

Note. To do this, enable symbolic template templates (in the administrator backend, go to "System"> "Configuration"> "Advanced"> "Developer", expand "Template Settings" and set "Allow Links" to "Yes").

Files related to test.phtml

  • 1column.phtml
  • 2columns-left.phtml
  • 2columns-right.phtml
  • 3columns.phtml
  • empty.phtml
  • popup.phtml
  • print.phtml
  • redirect.phtml
0
source

This is a working solution that I built that definitely does the job of switching the design / design theme through the controller_front_init_before event.

Of course, you can check some request parameters inside the changeConfigNode() method with Mage::app()->getRequest()->getParam('switch') and just add the switch/1 request parameter 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'); } 

No additional checks, but it can help you! Good luck

+1
source

Source: https://habr.com/ru/post/948661/


All Articles