I've got an issue with Magento xml layouts. I've been trying to change the page template when a customer is logged in, but only for specific pages in the layout. I've tried using the <customer_logged_in> handle in my xml but I can't get it to reference another handle specifically.
Non-working example of what I'd like it to do:
<catalog_product_view>
<customer_logged_in>
<reference name="root">
<action method="setTemplate"><template>page/3columns.html</template></action>
</reference>
</customer_logged_in>
<customer_logged_out>
<reference name="root">
<action method="setTemplate"><template>page/2columns-left.html</template></action>
</reference>
</customer_logged_out>
</catalog_product_view>
Is this possible to accomplish with the XML layout system or should I be looking at another approach?
Unfortunately with Magento layouts, there is no way to filter between two layout handles.
What I would recommend is slightly different and more complex, but I believe that it will give you the flexibility that you need.
You will need to create a module to do this. I am including all code necessary to do this.
Module Definition:
app/etc/Your_Module.xml
<config>
<modules>
<Your_Module>
<codePool>local</codePool>
<active>true</active>
</Your_Module>
</modules>
</config>
Config XML:
app/code/local/Your/Module/etc/config.xml:
<config>
<global>
<modules>
<Your_Module>
<version>1.0</version>
</Your_Module>
</modules>
</global>
<frontend>
<controller_action_layout_generate_blocks_after>
<observers>
<your_module_name>
<type>singleton</type>
<class>Your_Module/Observer</class>
<method> controllerActionLayoutGenerateBlocksAfter</method>
</your_module_name>
</observers>
</controller_action_layout_generate_blocks_after>
</frontend>
</config>
The code that makes it work
Then at this path app/code/local/Your/Module/Model/Observer.php:
<?php
class Your_Module_Model_Observer
{
public function controllerActionLayoutGenerateBlocksAfter ($observer)
{
$controller = $observer->getAction();
if ($controller->getFullActionName() == 'catalog_product_view') {
$layout = $controller->getLayout();
$rootBlock = $layout->getBlock('root');
if (Mage::getSingleton('customer/session')->isLoggedIn()) {
$rootBlock->setTemplate('page/1-column.html');
} else {
$rootBlock->setTemplate('page/2-columns.html');
}
}
}
}
(I took a few tips from: update layout programatically in magento event observer)
Related
When we choose one of the option below, the field 'title' automatically filled with selected value from carrier options.
I want to do the same for 'number' field, it would be filled with something when I choose my custom carrier. Is there any way to modify this tracking form? If yes, how?
Thank's in advance
Add following observer in your module's config.xml
<events>
<adminhtml_block_html_before>
<observers>
<add_script_on_shipment>
<class>yourmodule/observer</class>
<method>addScript</method>
</add_script_on_shipment>
</observers>
</adminhtml_block_html_before>
</events>
Put following code in Observer.php
public function addScript($observer) {
$block = $observer->getEvent()->getBlock();
if (($block instanceof Mage_Adminhtml_Block_Sales_Order_Shipment_View_Tracking) && $block->getType() != 'core/template' /*&& is your carrier active*/) {
$shipment = $block->getShipment();
$_child = clone $block;
$_child->setType('core/template');
$block->setChild('calling_block', $_child);
$block->setTemplate('yourmodule/custom_script.phtml');
}
}
add following code with required modifications in custom_script.phtml
<?php echo $this->getChildHtml('calling_block');?>
<script type="text/javascript">
/*your custom javascript code to bind onchange event*/
</script>
Look in the file app/design/adminhtml/default/default/layout/sales.xml, tracking.phtml is used several times. If this change is for a module then create a layout file 'yourmodule.xml' and enable it from your config file. Otherwise name it 'local.xml'. It's contents will have to be an update something like this:
<?xml version="1.0"?>
<layout>
<adminhtml_sales_order_shipment_new>
<reference name="shipment_tracking">
<action method="setTemplate">
<template>your/new/tracking.phtml</template>
</action>
</reference>
</adminhtml_sales_order_shipment_new>
</layout>
Also if you want to minimize number of copypasted layout statements you can use
<update handle="handle_name" /> inside different controller action handles. For example:
<my_handle_name>
<reference name="shipment_tracking">
<action method="setTemplate">
<template>your/new/tracking.phtml</template>
</action>
</reference>
</my_handle_name>
<adminhtml_sales_order_shipment_new>
<update handle="my_handle_name"/>
</adminhtml_sales_order_shipment_new>
Hi i just created custom module in magento and its frontend doesn't work.
The config file :
<?xml version="1.0"?>
<config>
<modules>
<Shareino_Sync>
<version>0.1.0</version>
</Shareino_Sync>
</modules>
<global>
<helpers>
<sync>
<class>Shareino_Sync_Helper</class>
</sync>
</helpers>
<blocks>
<sync>
<class>Shareino_Sync_Block</class>
</sync>
</blocks>
</global>
<frontend>
<routers>
<sync>
<use>standard</use>
<args>
<module>Shareino_Sync</module>
<frontName>shareinosync</frontName>
</args>
</sync>
</routers>
<layout>
<updates>
<sync>
<file>shareino_front.xml</file>
</sync>
</updates>
</layout>
</frontend>
</config>
The layout file :
# File in : app/design/frontend/default/default/layout/shareino_front.xml
<layout version="0.1.0">
<sync_index_index>
<reference name="content">
<block type="sync/sync" name="sync" template="sync_index.phtml" />
</reference>
</sync_index_index>
</layout>
And sync_index.phtml :
# file in app/design/frontend/default/default/template/sync_index.phtml
<h1>
Test Text
</h1>
I created a block that named Sync.php
class Shareino_Sync_Block_Sync extends Mage_Core_Block_Template
{
public function myfunction()
{
return "Hello tuts+ world";
}
}
At the end my controller :
class Shareino_Sync_IndexController extends Mage_Core_Controller_Front_Action
{
public function indexAction(){
$this->loadLayout();
$this->renderLayout();
}
public function testAction(){
echo "index Action";
}
}
I think i done every think well , but when i load the action url in browser it doesn't my layout. please help me to know my wrong.
Check your current theme, maybe it is not default/default. If it is different, just place layout and templates under this theme. Or put it into base/default theme for compatibility with all themes.
Make sure the module is registered in app/etc/modules/Shareino_Sync.xml.
And the last, maybe your module is disabled for output. Goes to System->Configuration->Advanced->Advanced->Disable Module Output find your module and make sure it is enabled.
you should always put your module layout files AND template files under base/default the reason is because the fallback theme mechanism of Magento first look for those files in your_package/your_theme then under your_package/default then under base/default. So if you put those files under default/default and your package is not default those files will never be found
I'm working on a custom module to display CMS content. I have a custom front controller which is working as expected. I'm able to call various front actions from the controller. I am using an existing template, which is also displaying as it should. I'm also loading a layout update xml file, from which I was able to remove the product menu, which I don't need, and add a reference block for my custom block's template file.
I know the correct template override file is loading, as I'm testing with the following:
<?php echo __FILE__ . " loaded <br>"; ?>
Which is echoing the correct filename.
However, when I call my custom block method from that same template file, I get nothing.
My module namespace/module is Cmpreshn/Projects. Following is what I have so far:
Config file in
app/code/local/Cmpreshn/Projects/etc/config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Cmpreshn_Projects>
<version>0.1.0</version>
</Cmpreshn_Projects>
</modules>
<frontend>
<routers>
<projects>
<use>standard</use>
<args>
<module>Cmpreshn_Projects</module>
<frontName>education</frontName>
</args>
</projects>
</routers>
<layout>
<updates>
<projects>
<file>projects.xml</file>
</projects>
</updates>
</layout>
</frontend>
<global>
<blocks>
<projects>
<class>Projects_Block_List</class>
</projects>
</blocks>
</global>
</config>
Front controller in
app/code/local/Cmpreshn/Projects/controllers/ProjectsController.php
<?php
class Cmpreshn_Projects_ProjectsController extends Mage_Core_Controller_Front_Action {
public function indexAction(){
$this->listAction();
}
public function listAction(){
echo "list action called<br>";
/* get request and save params to object */
$this->request = Mage::app()->getRequest();
/* layout overrides for this module in app/design/frontend/default/pmc1/layout/projects.xml */
$this->loadLayout();
/* use the education template */
$this->getLayout()->getBlock("root")->setTemplate("page/pmc_education.phtml");
/* render the layout */
$this->renderLayout();
}
}
XML updates in
app/design/frontend/default/pmc1/layout/projects.xml
<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.1.0">
<projects_projects_list>
<remove name="top.menu"/>
<reference name="content">
<block type="page/html" name="page" template="cmpreshn/projects/list.phtml" />
</reference>
</projects_projects_list>
</layout>
Template overrides and call to custom block in
app/design/frontend/default/pmc1/template/cmpreshn/project/list.phtml
<?php echo __FILE__ . " loaded <br>"; ?>
<?php echo $this->getProjectsList(); ?>
Last but not least, my custom block class in
app/code/local/Cmpreshn/Proejcts/Block/List.php
<?php
class Cmpreshn_Projects_Block_List extends Mage_Core_Block_Template {
public function _construct() {
parent::__construct();
echo "projects list block constructor called<br>";
} // end constructor
public function getProjectsList() {
echo "getProjectsList called <br>";
return("getProjectsList called");
}
} // end class
As I mentioned previously, I am getting the output from the first line of my list.phtml template file, but no output from my custom block method, and no indication that my block is loading (no output from block _construct() method either )
Any help is appreciated. I'm ready to pull my eyes out over this...
I just observed your code and found the following errors:
Registeration of block in registering module file (config.xml) seems wrong.
<global>
<blocks>
<projects>
<class>Cmpreshn_Projects_Block</class> <!-- Not Projects_Block_List -->
</projects>
</blocks>
</global>
The type attribute is wrong in Block element of layout file (projects.xml). You should not call page/html instead you should call projects/list.
There might be more typos. but I could found the above two only. I hope this solves your problem.
change the block type to projects/list in your projects.XML file like this
<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.1.0">
<projects_projects_list>
<remove name="top.menu"/>
<reference name="content">
<block type="projects/list" name="page" template="cmpreshn/projects/list.phtml/>
</reference>
</projects_projects_list>
</layout>
you may get the output now.
I'm trying to add a content block to Magento, which should be visible on every side below the main content. I want to archive this with a custom extension, so I can copy this extension and it workes without touching core design files.
My extension includes the following layout update:
<default>
<reference name="content">
<block type="mymod/blockname" name="myblockname" after="-" template="mymod/block.phtml"/>
</reference>
</default>
My problem is, that the attribute after="-" is not working. The block always showes up at the top of the content block. Seems before and after have no consequence.
If I move the block to i.e. footer, the attributes before and after are working fine.
How can I place my block at the bottom of block "content"
As far as I can see the problem is that you specify your block in the "default" layout handle while most of the content in the "content" block is added by other layout handles which are applied later. That's why the added dependencies in your XML registration file (mentioned by Fabian) are not helping.
Please consider these two options depending on your needs:
1. If you really want to include your block on all frontend pages
In your XML layout file (local.xml or a custom one), add a new layout handle:
<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.1.0">
<!-- your other adjustments for default, category_product_view and so on go here -->
<add_my_block>
<reference name="content">
<block type="mymod/blockname" name="myblockname" after="-" template="mymod/block.phtml"/>
</reference>
</add_my_block>
</layout>
Now you create an event observer to inject your layout handle into your layout:
<?php
class YourCompany_YourExtension_Model_Observer
{
/**
* Adds a block at the end of the content block.
*
* Uses the event 'controller_action_layout_load_before'.
*
* #param Varien_Event_Observer $observer
* #return YourCompany_YourExtension_Model_Observer
*/
public function addBlockAtEndOfMainContent(Varien_Event_Observer $observer)
{
$layout = $observer->getEvent()->getLayout()->getUpdate();
$layout->addHandle('add_my_block');
return $this;
}
}
Then you register the event observer in your XML extension configuration file (config.xml):
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<modules>
<YourCompany_YourExtension>
<version>0.0.1</version>
</YourCompany_YourExtension>
</modules>
<frontend>
<events>
<controller_action_layout_load_before>
<observers>
<mymod_add_block_at_end_of_main_content>
<type>singleton</type>
<class>mymod/observer</class>
<method>addBlockAtEndOfMainContent</method>
</mymod_add_block_at_end_of_main_content>
</observers>
</controller_action_layout_load_before>
</events>
<!-- declaring your layout xml etc. -->
</frontend>
<global>
<!-- declaring your block classes etc. -->
<models>
<mymod>
<class>YourCompany_YourExtension_Model</class>
</mymod>
</models>
</global>
</config>
Now your block should end up below the other blocks. I tested this successfully for the homepage, customer login page and category view page. If you have to exclude your block on a few pages, you can check in your event observer if the block should be excluded on that certain page.
2. If you want to include your block only on some pages
Add a layout handle to your XML layout file just as we did before but instead of creating and registering an event observer, just tell your XML layout file to use the custom layout handle in some areas:
<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.1.0">
<catalog_category_default>
<update handle="add_my_block" />
</catalog_category_default>
<catalog_category_layered>
<update handle="add_my_block" />
</catalog_category_layered>
<cms_page>
<update handle="add_my_block" />
</cms_page>
<!-- and so on -->
<add_my_block>
<reference name="content">
<block type="mymod/blockname" name="myblockname" after="-" template="mymod/block.phtml"/>
</reference>
</add_my_block>
</layout>
I'm trying to develop an extension that would add a form on the Admin side of Magento, but, for some reason, I can't seem to be able to even get Magento Administration to load when my module is installed. I'm at the very beginning of the development, and I'm stuck on an error that has been reported several times on StackOverflow. Unfortunately, none of the answers seem to help in my case.
The error I get is *Fatal error: Class 'Mage_Mycompany_Logviewer_Helper_Data' not found in C:\XAMPP\htdocs\magento\app\Mage.php on line 546*. That should mean that Magento can't find the helper class, but it's there and its name matches the one it's looking for (except for the "Mage_" at the beginning, that I never used in any other extension anyway).
Update 2012/07/29
The error occurs as soon as I log in into Magento Admin. When I click "Login", all I get is an error page, nothing is rendered.
Here's the content of all the files I have so far.
config.xml
<?xml version="1.0"?>
<config>
<modules>
<Mycompany_Logviewer>
<version>0.1.0</version>
</Mycompany_Logviewer>
</modules>
<global>
<models>
<logviewer>
<class>Mycompany_Logviewer_Model</class>
</logviewer>
</models>
<blocks>
<logviewer>
<class>Mycompany_Logviewer_Block</class>
</logviewer>
</blocks>
<helpers>
<logviewer>
<class>Mycompany_Logviewer_Helper</class>
</logviewer>
</helpers>
</global>
<admin>
<routers>
<adminhtml>
<args>
<modules>
<mycompany_logviewer after="Mage_Adminhtml">Mycompany_Logviewer_Adminhtml</mycompany_logviewer>
</modules>
</args>
</adminhtml>
</routers>
</admin>
<adminhtml>
<menu>
<mycompany translate="title" module="mycompany_logviewer">
<title>Mycompany</title>
<sort_order>90</sort_order>
<children>
<form translate="title" module="mycompany_logviewer">
<title>Form</title>
<sort_order>10</sort_order>
<action>adminhtml/logviewer</action>
</form>
</children>
</mycompany>
</menu>
<acl>
<resources>
<all>
<title>Allow Everything</title>
</all>
<admin>
<children>
<mycompany>
<title>Mycompany</title>
<sort_order>90</sort_order>
<children>
<form>
<title>Form</title>
<sort_order>10</sort_order>
</form>
</children>
</mycompany>
</children>
</admin>
</resources>
</acl>
</adminhtml>
</config>
Data.php (Helper)
class Mycompany_Logviewer_Helper_Data extends Mage_Core_Helper_Abstract
{
}
LogviewerController.php (Controller)
class Mycompany_Logviewer_Adminhtml_LogviewerController extends Mage_Adminhtml_Controller_Action
{
/**
* View form action
*/
public function indexAction() {
$this->loadLayout();
$this->_setActiveMenu('Mycompany/form');
$this->_addBreadcrumb(Mage::helper('Mycompany_Logviewer')->__('Form'), Mage::helper('Mycompany_Logviewer')->__('Form'));
$this->renderLayout();
}
/**
* Check allow or not access to ths page
*
* #return bool - is allowed to access this menu
*/
protected function _isAllowed()
{
return Mage::getSingleton('admin/session')->isAllowed('Mycompany/form');
}
}
Mycompany_Logviewer.xml (configuration file)
<?xml version="1.0"?>
<config>
<modules>
<Mycompany_Logviewer>
<active>true</active>
<codePool>local</codePool>
</Mycompany_Logviewer>
</modules>
</config>
All the above have been copied from an example I found online, I just replaced the Namespace and the Module name with Mycompany and Logviewer, respectively. I'm pretty sure it's something obvious I forgot, but I can't figure out what it could be. Thanks for the help.
The first thing that jumps out is that you are registering a module with the name of Procedo_Logviewer - when in fact it should be Mycompany_Logviewer
So, Mycompany_Logviewer.xml should be as follows:
<?xml version="1.0"?>
<config>
<modules>
<Mycompany_Logviewer>
<active>true</active>
<codePool>local</codePool>
</Mycompany_Logviewer>
</modules>
</config>
Clear cache after changing
EDIT
Looking more closely at your controller, I can also see that you are calling your helper like so:
Mage::helper('Mycompany_Logviewer')
You should be calling your helper like this instead:
Mage::helper('logviewer')
EDIT 2
Another issue is present in your config.xml
module="mycompany_logviewer"
Should be
module="logviewer"
This correlates to the helper node you declared in your xml i.e.
<helpers>
<logviewer>
<class>Mycompany_Logviewer_Helper</class>
</logviewer>
</helpers>
I had similar problem. Solution was putting company name in like this:
<helpers>
<Mycompany_Logviewer>
<class>Mycompany_Logviewer_Helper</class>
</Mycompany_Logviewer>
</helpers>
$myHelper= Mage::helper('Mycompany_Logviewer');