Im a newbie at Magento. Im trying to build a module which dynamically inserts code xml into layout xml before its rendered -
something similar to how CMS>pages have been build.
Just like how we can specify layout xml in the design section of a page (admin > cms > page), I would like to insert into layout.xml through my module.
Basically, I would like to
have an admin section from where I can enter layout code through a
form and store in database - I have figured out this part
have Magento pull these pieces of code stored in the database and create an xml file before the layout files are aggregated and interpreted. - Im unable to build this portion.
Any help would be appreciated.
Just a little enlightment
You can add those layout xml by using observer,
Let's say you want those layout xml added before the xml is generated
We can use event controller_action_layout_generate_xml_before
Here's the sample code (in config.xml)
<frontend>
<events>
<controller_action_layout_generate_xml_before>
<observers>
<add_new_layout>
<class>test/observer</class>
<method>addNewLayout</method>
</add_new_layout>
</observers>
</controller_action_layout_generate_xml_before>
</events>
</frontend>
Here's the Observer.php
public function addNewLayout($observer){
$layout = $observer->getEvent()->getLayout();
$update = $layout->getUpdate();
//$action = $observer->getEvent()->getAction();
//$fullActionName = $action->getFullActionName();
//in case you're going to add some conditional (apply these new layout xml on these action or other things, you can modify it by yourself)
//here is the pieces of layout xml you're going to load (you get it from database)
$xml = "<reference name='root'><remove name='footer'></remove></reference>";
$update->addUpdate($xml);
return;
}
Another posibility is to use the core_layout_update_updates_get_after-event and a placeholder (non-existing) layout xml:
<frontend>
<layout>
<updates>
<foobar>
<file>foo/bar.xml</file>
</foobar>
</updates>
</layout>
<events>
<core_layout_update_updates_get_after>
<observers>
<foobar>
<type>singleton</type>
<class>foobar/observer</class>
<method>coreLayoutUpdateUpdatesGetAfter</method>
</foobar>
</observers>
</core_layout_update_updates_get_after>
</events>
</frontend>
Example PHP in your observer:
/**
* Event dispatched when loading the layout
* #param Varien_Event_Observer $observer
*/
public function coreLayoutUpdateUpdatesGetAfter($observer)
{
/** #var Mage_Core_Model_Config_Element $updates */
if (Mage::getStoreConfig('foobar/general/enabled')) {
$file = Mage::getStoreConfig('foobar/general/layout_xml');
if (!empty($file)) {
$updates = $observer->getUpdates();
if ($updates->foobar) {
$updates->foobar->file = $file;
}
}
}
}
Related
I'm would like to use lesti:FPC with a module I developed.
To enable SEO friendly urls ALL requests to the module are sent to the module index action, and there a template is dynamically loaded. How can I make lesti:FPC work under this scenario?
On the module layout file (../layout/addon.xml) I have:
<block type="addon/index" name="addon_index" template="addon/index.phtml"/>
On the module indexAction I have:
if($condition)
{
$this->getLayout()->getBlock('addon_index')->setTemplate('addon/a.phtml');
}
else
{
$this->getLayout()->getBlock('addon_index')->setTemplate('addon/b.phtml');
}
Would adding 'addon_index' to the lesti:FPC layout-handles be enough to get my module pages cached?
Calling Dynamic Block in Lesti Fpc depends on conditions can be done using observer
**Config.xml**
<frontend>
<events>
<core_block_abstract_to_html_before>
<observers>
<atwix_test>
<type>model</type>
<class>namspace_test/observer</class>
<method>insertBlock</method>
</atwix_test>
</observers>
</core_block_abstract_to_html_before>
</events>
</frontend>
class Namespace_Test_Model_Observer
{
public function insertBlock($observer)
{
/** #var $_block Mage_Core_Block_Abstract */
/*Get block instance*/
$_block = $observer->getBlock();
/*get Block type*/
$_type = $_block->getType();
/*Check block type*/
if ($_type == 'catalog/product_price') {
/*Clone block instance*/
$_child = clone $_block;
/*set another type for block*/
$_child->setType('test/block');
/*set child for block*/
$_block->setChild('child', $_child);
/*set our template*/
$_block->setTemplate('at.phtml');
}
}
}
And finally, here is a template at.phtml code:
echo $this->getChildHtml('child');
Hope it will help you.
I am little bit stuck with adding top links in my custom phtml.I removed the links block in my xml <remove name="top.links"/> , now after some condtion become true i want to add this block again.When i use this code for top menu it works but not for links
$block = Mage::getSingleton('core/layout');
echo $block->createBlock('catalog/navigation')->setTemplate('catalog/navigation/top.phtml')->toHtml();
This works and disply top menu.But the below code doesn't show anything.
$block = Mage::getSingleton('core/layout');
echo $block->createBlock('page/template_links')->setTemplate('page/template/links.phtml')->toHtml();
Any help ???
After using observer i solve my problem for time being.I think this is alternate way.In my config i define oberser like :
<frontend>
<events>
<controller_action_layout_generate_xml_before>
<observers>
<Mymodule>
<class>Mymodule_Model_Observer</class>
<method>addmyblock</method>
</Mymodule>
</observers>
</controller_action_layout_generate_xml_before>
</events>
</frontend>
while in oberser simply check and remove block :
<?php
class Mymodule_Model_Observer
{
public function addmyblock(Varien_Event_Observer $observer)
{
if(Mage::getStoreConfig("mymodule/general/enable")==1)
{
$layout = $observer->getLayout();
$layout->getUpdate()->addUpdate('<remove name="top.search"/>
<remove name="top.links"/>');
$layout->generateXml();
}
}
}.
Also i removed the code from xml <remove name="top.links"/>.So the code only remove block when the condition become true.
I have a custom admin config field type in Magento and I would like to load up a CSS file for that config field(also javascript too).
The field class:
class Company_Module_Block_Configure extends Mage_Adminhtml_Block_System_Config_Form_Field
{
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
{
// I would like to load the CSS and Javascripts files to the head.
return "Here comes the field output";
}
}
I have tried this, but no luck. Maybe the head rendered sooner:
Mage::app()->getLayout()->getBlock('head')->addCss('My css url...');
Or somehow I should Observe some kind of "before_body_end" event. Is it possible?
Update #1:
I have started to go through the before_body_end event:
Config.xml
<config>
<global>
<events>
<core_block_abstract_to_html_before>
<observers>
<test>
<class>Company_Module_Model_Observer</class>
<method>test</method>
</test>
</observers>
</core_block_abstract_to_html_before>
</events>
</global>
</config>
And the observed method looks like this:
public function test($block){
if($block->getEvent ()->getBlock()->getNameInLayout() == 'before_body_end'){
}
}
I'm new on magento and trying to write little extension for it (magento 1.7).
I have created tab in customer->edit, it prints multiselect, thats ok, the problem is that i cant get in observer file to catch multiselect options before saving and save them to my custom table in database.
there is some code snippets:
app/code/local/Gone/Brands/etc/config.xml
<adminhtml>
<layout>
<updates>
<customertab>
<file>customertab.xml</file>
</customertab>
</updates>
</layout>
<events>
<customer_save_after>
<observers>
<brands_hide_manufacturers>
<type>model</type>
<class>Gone_Brands_Model_Observer</class>
<method>saveHideManufacturers</method>
</brands_hide_manufacturers>
</observers>
</customer_save_after>
</events>
</adminhtml>
app/code/local/Gone/Brands/Model/Observer.php
<?php
class Gone_Brands_Model_Observer
{
public function _construct()
{
echo "ssssssssssssssssssssssssssss";
echo "<script>alert('aaa');</script>";
}
public function saveHideManufacturers() {
echo "ssssssssssssssssssssssssssss";
echo "<script>alert('bbbb');</script>";
}
}
Maye there are other solutions how to catch form from customer->edit -> my created tab with custom field?
Thank you.
==================================================================================
Finally, four hours spent for this. Maybe this helps for someone else.
config.xml
customer_save_after -> change to -> adminhtml_customer_save_after
Now works.
Finally, four hours spent for this. Maybe this helps for someone else.
config.xml
customer_save_after -> change to -> adminhtml_customer_save_after
Now works.
In magento you doesn't link to a class with its full class name.. you must use the framework :
replace :
<class>Gone_Brands_Model_Observer</class>
by :
<class>gonebrands/observer</class>
"gonebrands" (or whatever) refers to your XML node defining your MODEL layer in your config.xml
Event definition must be inside "global" tag. Also
you don't need a _construct method in your observer class
<global>
<events>
<customer_save_after>
<observers>
<brands_hide_manufacturers>
<type>singleton</type>
<class>Gone_Brands_Model_Observer</class>
<method>saveHideManufacturers</method>
</brands_hide_manufacturers>
</observers>
</customer_save_after>
</events>
</global>
I cant provide any code because that is part of the question, but I am sure if you guide me in the right direction I can paste the code from the files you tell me.
I enabled product reviews on my site:
However the product page title and the product review page title its the same and its giving me lots of duplicate pages for my SEO efforts.
examples:
normal page
http://www.theprinterdepo.com/hp-laser-p2015dn-printer-cb368a
same product review page
http://www.theprinterdepo.com/review/product/list/id/1133/
any idea?
thanks
I am not aware of any feature out of the box that allows you to specify different titles for product review pages. I could be wrong though?
So, that leaves two methods you can use to achieve this.
Core block override
Event/Observer
I would opt for option 2 here. Even with this option there are still various ways to achieve this. Here is one of them...
So, once you have created your module, you will need to declare the observer in your config.xml:
<?xml version="1.0"?>
<config>
<!-- other config xml -->
<frontend>
<events>
<controller_action_layout_render_before_review_product_list>
<observers>
<productmeta>
<class>YourCompany_YourModule_Model_Observer</class>
<method>controller_action_layout_render_before_review_product_list</method>
</productmeta>
</observers>
</controller_action_layout_render_before_review_product_list>
</events>
</frontend>
<!-- other config xml -->
</config>
Then your observer would be similar to this...
<?php
class YourCompany_YourModule_Model_Observer
{
/**
* #pram Varien_Event_Observer $observer
* #return void
*/
public function controller_action_layout_render_before_review_product_list(Varien_Event_Observer $observer)
{
$title = "Your new page title";
Mage::app()->getLayout()->getBlock('head')->setData('title', $title);
}
}