Magento : How to add handle through observer - magento

I am trying to use addHandle(), but using the following generates error:
public function HandleMe($observer)
$update = $observer->getEvent()->getLayout()->getUpdate();
$update->addHandle('handlename');
raises a "Fatal error: Call to a member function getUpdate()"

You have to load core/layout before you update the layout, So try follow below code,
public function addCustomHandles($observer) {
$update = Mage::getSingleton('core/layout')->getUpdate();
//Your code here..
}
Or refer below link,
Link 1
Link 2

try using following approach :
First add this to your config.xml in yourcustommodule:
<config>
<frontend>
<events>
<controller_action_layout_load_before>
<observers>
<yourcustomtheme_observer>
<class>yourcustomtheme/observer</class>
<method>addHandles</method>
</yourcustomtheme_observer>
</observers>
</controller_action_layout_load_before>
</events>
</frontend>
</config>
And then add following method to your observer
class YourPackage_YourCustomTheme_Model_Observer extends CLS_Core_Model_Abstract
{
public function addHandles($observer) {
$category = Mage::registry('current_category');
if ($category instanceof Mage_Catalog_Model_Category) {
$update = Mage::getSingleton('core/layout')->getUpdate();
$fertilility = (count($category->getChildrenCategories()->getData())) ? 'parent' : 'nochildren';
$update->addHandle('catalog_category_' . $fertilility);
}
return $this;
}
}
PS : this is only for reference, so that you can check whether you are correctly using observer and handles or not.

Related

Call to a member function insert() on a non-object Magento

I am Using Observer Event in my custom module's Config.xml
<controller_action_layout_render_before>
<observers>
<Test_Check_Model_Observer>
<class>Test_Check_Helper_Data</class>
<method>checkValidi</method>
</Test_Check_Model_Observer>
</observers> </controller_action_layout_render_before>
Now in Test/Check/Helper/Data checkValidi Method I am inserting a block in Content.
>
class Test_Check_Helper_Data extends Mage_Core_Helper_Abstract {
> public function checkValidi($observer) {
> $layout = Mage::app()->getLayout();
> $content = $layout->getBlock('content');
> $block = 'hello! I am Working';
> $content->insert($block);
> }
But In Frontend When I am Filling Checkout billing and other information it gives me an Error Call to a member function insert() on a non-object in right side bar of Your Checkout Progress ,Please Give me any Solution for that Thanks
If you look at layout of checkout module checkout.xml you can see that some handles do not have content block. Eg, checkout_onepage_progress_billing or checkout_onepage_progress_shipping
So, you will get non-object error with your code. I think you should check $block variable before calling method.
$layout = Mage::app()->getLayout();
$content = $layout->getBlock('content');
if ($content) {
$block = 'hello! I am Working';
$content->insert($block);
}
It is not good idea to call helper from observer.
Observer always call a model file ,it did not class
i have modify and code config.xml code is
<global>
<models>
<testcheck>
<class>Test_Check_Model</class>
</testcheck>
</models>
</global>
<events>
<controller_action_layout_render_before>
<observers>
<test_check_codel_observer>
<type>singleton</type>
<class>testcheck/observer</class>
<method>your_function_name</method>
</test_check_codel_observer>
</observers>
</controller_action_layout_render_before>
</events>
And then Create Observer Observer.php file Under app/code/YourcodePoll/Test/Check/Model/
and below
code in Observer.php
is
<?php class Test_Check_Model_Observer
{
public function your_function_name($observer){
$block = $this->getLayout()
->createBlock('core/text', 'example-block')
->setText('<h1>This is a text block</h1>');
$observer->getEvent()->getLayout()->getBlock('content')->append($block);
//$observer->getEvent()->getLayout()->getUpdate();
}
}

Magento Custom Router Lost Layout Object

It seems like everything is being properly configured and I can get the output that I want but I would prefer not echoing the layout object directly from my controller:
Here is what Im working with
config.xml
<config>
<modules>
<ALS_Bestselling>
<version>0.1.0</version>
</ALS_Bestselling>
</modules>
<global>
<models>
<bestselling>
<class>ALS_Bestselling_Model</class>
</bestselling>
</models>
<blocks>
<bestselling>
<class>ALS_Bestselling_Block</class>
</bestselling>
</blocks>
<helpers>
<bestselling>
<class>ALS_Bestselling_Helper</class>
</bestselling>
</helpers>
</global>
<frontend>
<layout>
<updates>
<als_bestselling>
<file>bestselling.xml</file>
</als_bestselling>
</updates>
</layout>
</frontend>
<default>
<web>
<routers>
<bestselling_router>
<area>frontend</area>
<class>ALS_Bestselling_Controller_Router</class>
</bestselling_router>
</routers>
</web>
<shorturls>
</shorturls>
</default>
</config>
and
#File: Controller/Router.php
<?php
class ALS_Bestselling_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
{
private static $_module = 'bestsellers';
private static $_realModule = 'ALS_Bestselling';
private static $_controller = 'index';
private static $_controllerClass = 'ALS_Bestselling_Controller_Index';
private static $_action = 'view';
public function initControllerRouters($observer)
{
$front = $observer->getEvent()->getFront();
$front->addRouter('bestselling', $this);
}
public function collectRoutes()
{
// nothing to do here
}
public function match(Zend_Controller_Request_Http $request)
{
$this->_request = $request;
$front = $this->getFront();
$identifier = trim($request->getPathInfo(), '/');
if(!substr($identifier,0,strlen('bestsellers')) == 'bestsellers'){
return false;
}else{
//$rewrite = Mage::getModel('core/url_rewrite');
$route_params = str_replace ( "bestsellers/" , "" , $identifier );
$rewrite = Mage::getModel('core/url_rewrite');
$rewrite->setStoreId(1);
$rewrite->loadByRequestPath($route_params);
$category_route = $rewrite->getIdPath();
//If no route exists for category send to a different router
if(!$category_route != ""){
return false;
}//Otherwise send the parameters to the request
else{
$id = str_replace ( "category/" , "" , $category_route );
$this->_request->setParam('id',$id);
}
$this->_setRequestRoute();
$this->_dispatch();
return true;
}
}
protected function _setRequestRoute()
{
$this->_request->setModuleName(self::$_module);
$this->_request->setControllerName(self::$_controller);
$this->_request->setActionName(self::$_action);
$this->_request->setControllerModule(self::$_realModule);
}
protected function _dispatch()
{
$this->_request->setDispatched(true);
$controller = Mage::getControllerInstance(self::$_controllerClass, $this->_request, $this->_response);
$controller->dispatch(self::$_action);
}
}
and
File: Controller/Index.php
class ALS_Bestselling_Controller_Index extends Mage_Core_Controller_Front_Action{
public function viewAction(){
$layout = Mage::app()->getLayout();
$layout->generateXml()->generateBlocks();
$render = $layout->getBlock('root')->toHtml();
echo $render;
}
}
The previous works but the following:
$update = $this->getLayout()->getUpdate();
$update->addHandle('default');
$this->renderLayout();
throws an error Call to a member function appendBody() on a non-object.
Is this how I am suppose to do this or is there something missing from the recipe?
Custom routing classes are on the fringe of what most developers do with Magento — the standard approach would be to setup a standard module controller with a frontname of bestselling, or create your feature in a non-seo friendly way and then create a rewrite entity/object to SEO-ify it.
I, however, have a soft spot for custom routing objects, even if there's little in the way of best community practices behind them. Without a line number, it sounds like your exception
Call to a member function appendBody() on a non-object
comes from the following code
#File: app/code/core/Mage/Core/Controller/Varien/Action.php
$this->getResponse()->appendBody($output);
Given the definition for getResponse
public function getResponse()
{
return $this->_response;
}
It sounds like your controller object doesn't have a proper response object set.
Looking at your controller instantiation code
$controller = Mage::getControllerInstance(self::$_controllerClass, $this->_request, $this->_response);
You're referencing a $this->_response property — but your router class and the abstract router class don't have this property. It's impossible to say based on what you've posted, but this is probably your problem. Take a look at how the standard router's match method does it.
#File: app/code/core/Mage/Core/Controller/Varien/Router/Standard.php
//...
$controllerInstance = Mage::getControllerInstance($controllerClassName, $request, $front->getResponse());
So, use the front-controller object to grab the response object, pass that into the getCongrollerInstance factory method, and you should be good to go (or at least onto the next problem)

Add button to catalog category in magento

I want to add new button to category page on admin side with delete category and save category.I try the way to override the block Catalog_Category_Edit_Form but didn't work.My xml code is :
<adminhtml>
<rewrite>
<Catalog_Category_Edit_Form>Mymodule_Block_Rewrite_Editcate</Catalog_Category_Edit_Form>
</rewrite>
</adminhtml>
While my block code is
<?php
class Mymodule_Block_Rewrite_Editcate extends Mage_Adminhtml_Block_Catalog_Category_Edit_Form
{
private $parent;
protected function _prepareLayout()
{
// Delete button
$this->parent = parent::_prepareLayout();
$this->removeButton('delete_button');
return $this->parent;
}
}.
Can anyone help me the right way ? In above code i try to remove button to check my code works .
Sorry guys i find a solution .My new xml is look like
<adminhtml>
<rewrite>
<catalog_category_edit_form>Mymodule_Block_Adminhtml_Catalog_Category_Edit_Form</catalog_category_edit_form>
</rewrite>
</adminhtml>
And my block code is :
<?php
class Mymodule_Block_Adminhtml_Catalog_Category_Edit_Form extends Mage_Adminhtml_Block_Catalog_Category_Edit_Form
{
protected function _prepareLayout()
{
parent::_prepareLayout();
$this->addAdditionalButton('update_button', array('name' => 'update_button','title'=>'Copy Category','type'=>"button",'label'=> Mage::helper('catalog')->__('Copy Category') ));
return parent::_prepareLayout();
}
}.
This is it.Mian function is addAdditionButton.Only pass parameter to it.I have override it.

capture Order completion status in observer in magento

Hi I want to catpture the order information when the oder is completed or close.I try different events like (sales_order_place_after) but didn't complete my requirements.I am completing orders form admin side and i create observer for capturing the information like
Xml :
<events>
<sales_order_place_after>
<observers>
<extra_options>
<class>My_Module_Model_Observer</class>
<method>salesConvertQuoteItemToOrderItem</method>
</extra_options>
</observers>
</sales_order_place_after>
</events>
Observer :
public function salesConvertQuoteItemToOrderItem($observer)
{
$order = $observer->getOrder();
$orders = $observer->getEvent()->getOrder();
if($order->getState() == Mage_Sales_Model_Order::STATE_COMPLETE){
echo "<pre>";
print_r($orders);exit;
}
}
Can anyone help ? Thanks in advance
You are doing everything right except you are listening to wrong event. You have to use sales_order_save_after instead.
Using sales_order_save_after is still good, but it just requires you also to check for the state (as Mischa suggests):
public function salesOrderSaveAfter($observer)
{
$order = $observer->getEvent()->getOrder();
if($order->getState() != Mage_Sales_Model_Order::STATE_COMPLETE) {
return $this;
}
if($order->getData('state') == $order->getOrigData('state')) {
return $this;
}
// do your stuff
return $this;
}
This works fine for me.

Adding a custom option using an extension in Magento

I'm creating a custom extension and I would like to add a custom option when a certain item is purchased.
For example, when the product "Name Tag" is purchased, the extension would detect that the specific product has been ordered and assign a custom option of "Year" to it. The user does not see this, but the attribute is added and displayed in the admin when viewing the order.
Are there any specific listeners our there to accomplish this?
EDIT Based on Ben's suggestions in the comments, I'm editing the comment to reflect progress I've made with the answers located here: https://stackoverflow.com/a/9496266/268165
I now have an extension running under Namespace_addYear and the following code running:
Namespace/addYear/etc/config.xml:
<?xml version="1.0" encoding="utf-8"?>
<config>
<modules>
<Namespace_addYear>
<version>1.0.0</version>
</Namespace_addYear>
</modules>
<global>
</global>
<frontend>
<events>
<catalog_product_load_after>
<observers>
<Namespace_addYear>
<type>model</type>
<class>addYear/observer</class>
<method>catalogProductLoadAfter</method>
</Namespace_addYear>
</observers>
</catalog_product_load_after>
</events>
</frontend>
</config>
Namespace/addYear/Model/Observer.php:
class Namespace_addYear_Model_Observer
public function catalogProductLoadAfter(Varien_Event_Observer $observer)
{
// set the additional options on the product
$action = Mage::app()->getFrontController()->getAction();
if ($action->getFullActionName() == 'checkout_cart_add')
{
// assuming you are posting your custom form values in an array called extra_options...
if ($options = $action->getRequest()->getParam('extra_options'))
{
$product = $observer->getProduct();
// add to the additional options array
$additionalOptions = array();
if ($additionalOption = $product->getCustomOption('additional_options'))
{
$additionalOptions = (array) unserialize($additionalOption->getValue());
}
foreach ($options as $key => $value)
{
$additionalOptions[] = array(
'label' => $key,
'value' => $value,
);
}
// add the additional options array with the option code additional_options
$observer->getProduct()
->addCustomOption('additional_options', serialize($additionalOptions));
}
}
}
}
The Observer.php was taken from the answer linked above. So far, I cannot get the store to do anything other than display a 404 page when I remove the tags in config.xml.
Is there anything someone can immediately see that is wrong?

Resources