Dispatching before and after events to Magento core actions

Featured Image

As we all probably know, there are some events in Magento that are dispatched by default.
We can easily hook on those events, but this is not a subject of this article.

What we are going to try now is to add custom event before and after some action in some of Magento’s controllers.

That way we don’t need to have event dispatched by default.
Of course, there are some actions that require little more things to handle (for example if you need something from session and session is cleared after action is run), but
for most of the situations there is a way to get what we need from that event.

For example, let’s take “addAction()” from “Mage_Checkout_CartController”.
We could rewrite that action using standard way and dispatch our own event in our rewriten class, but we can something like this:

Add this to your module config.xml

< ?xml version="1.0"?>
<config>
	<global>
    	<models>
	    	<dispatcher>
                  <class>Inchoo_Dispatcher_Model</class>
	       </dispatcher>
        </models>
	</global>
	<frontend>
		<events>
                        <!-- Hooking to Magento's default event "controller_action_predispatch" -->
			<controller_action_predispatch>
				<observers>
					<controller_action_before>
						<class>dispatcher/observer</class>
						<method>hookToControllerActionPreDispatch</method>
					</controller_action_before>
				</observers>
			</controller_action_predispatch>
                         <!-- Hooking to Magento's default event "controller_action_postdispatch" -->
			<controller_action_postdispatch>
				<observers>
					<controller_action_after>
						<class>dispatcher/observer</class>
						<method>hookToControllerActionPostDispatch</method>
					</controller_action_after>
				</observers>
			</controller_action_postdispatch>
                         <!-- Hooking to our own event "add_to_cart_before" -->
			<add_to_cart_before>
				<observers>
					<add_to_cart_before>
						<class>dispatcher/observer</class>
						<method>hookToAddToCartBefore</method>
					</add_to_cart_before>
				</observers>
			</add_to_cart_before>
                        <!-- Hooking to our own event "add_to_cart_after" -->
			<add_to_cart_after>
				<observers>
					<add_to_cart_after>
						<class>dispatcher/observer</class>
						<method>hookToAddToCartAfter</method>
					</add_to_cart_after>
				</observers>
			</add_to_cart_after>
		</events>
	</frontend>
</config>

Add this code to your module Observer.php

class Inchoo_Dispatcher_Model_Observer
{
    //this is hook to Magento's event dispatched before action is run
    public function hookToControllerActionPreDispatch($observer)
    {
        //we compare action name to see if that's action for which we want to add our own event
        if($observer->getEvent()->getControllerAction()->getFullActionName() == 'checkout_cart_add')
        {
            //We are dispatching our own event before action ADD is run and sending parameters we need
            Mage::dispatchEvent("add_to_cart_before", array('request' => $observer->getControllerAction()->getRequest()));
        }
    }
    public function hookToControllerActionPostDispatch($observer)
    {
         //we compare action name to see if that's action for which we want to add our own event
        if($observer->getEvent()->getControllerAction()->getFullActionName() == 'checkout_cart_add')
        {
            //We are dispatching our own event before action ADD is run and sending parameters we need
            Mage::dispatchEvent("add_to_cart_after", array('request' => $observer->getControllerAction()->getRequest()));
        }
    }
 	public function hookToAddToCartBefore($observer)
	{
            //Hooking to our own event
	    $request = $observer->getEvent()->getRequest()->getParams();
            // do something with product
	    Mage::log("Product ".$request['product']." will be added to cart.");
	}
	public function hookToAddToCartAfter($observer)
	{
            //Hooking to our own event
	    $request = $observer->getEvent()->getRequest()->getParams();
            // do something with product
	    Mage::log("Product ".$request['product']." is added to cart.");
	}
}

Of course, adjust naming to suit your needs.

For the end, I just want to point out that this code is not tested in production enviroment,
it is merely result of playing with events a bit.
What we have done now is that we have added 2 of our custom events before and after randomly chosen Magento core action without need to rewrite it’s class.

I’m sure that lots of people were playing with something similar, so if you feel like it, comment it. Maybe we can do something to improve it.

17
Top

Care to rate this post?

Author

Tomas Novoselic

Team Leader, Backend Developer

At Inchoo, Tomas is a Team Leader and Certified Magento Developer who handles Magento modifications at any level. He also works closely with clients on Magento projects of any size and difficulty.

Other posts from this author

Discussion 17 Comments

Add Comment
  1. This is good. People need to use event observers a lot more than overriding classes purely because multiple modules can easily work in the same environment together.

    We need to convince the Magento developers to provide hooks for *everything* :)

    It might make sense to formalise this in a open-source module we can use as a dependency to our own modules.

  2. @Nick Maybe I will formalise this in a open source module, but I think that it needs to offer little more functionality before that. For example how to do it in model classes etc. I have some ideas how to even inject event into the method body by overiding method directly from observer, but this is just part of my own playground at this moment. Maybe I come up with something really usable one day :)

  3. Dan Shields

    Thats pretty cool. Do you think there is a way to do this for models?

  4. Peter

    The Magento icon in the post heading has wrong colors :)

  5. Marcio

    You can use this form ?

    Thus this event is not triggered

  6. Volodymyr

    very useful, thanks

  7. Your code works as well, thanks!

    I’m looking for a way to hook also the adminhtml_controller_action_predispatch_start but it doesn’t seem to work in the same way of your example.

    I tried to do something like this:

                <adminhtml_controller_action_predispatch_start>
                    <observers>
                        <adminhtml_controller_action_predispatch_start>
                            <class>mymodule/observer</class>
                            <method>hookToAdminhtmlControllerActionPreDispatch</method>
                        </adminhtml_controller_action_predispatch_start>
                    </observers>
                </adminhtml_controller_action_predispatch_start>
    

    and in Observer.php:

    public function hookToAdminhtmlControllerActionPreDispatch($observer) {
    	Mage::Log('hello world');
    }
    

    but it doesn’t work and nothing happens.

    What’s wrong in that code?

  8. Kenny

    Same here, I have added a Mage::log(“Test”); in each method you provided and it doesn’t get added in the log. (Yes its enabled in the backend)

  9. @Simone and Kenny

    Try adding events in global directive. It should work for frontend and for backend…

  10. remya

    And also for testing a function instead of displaying some test text ,try adding some text message to a file .
    just like instead of Mage::log(“Test”); try to add “Test” to some file with append option ,by this way also you can check .and most important try to flush the mageno cache after every changes.
    Things will work for sure .
    Happy Coding :)

  11. Hi

    I don’t know why ‘adminhtml_controller_action_predispatch_start’ event only works in global directive not in adminhtml directive:

    mymodule/observer
    hookToAdminhtmlControllerActionPreDispatch

    Since thats an admin side event so assumed that adminhtml directive fits the best but i was wrong.

    Can inchooers highlight on this please?

    Thanks
    Regards

  12. Prat

    HI Tomas,
    It’s really very informative & useful article. I wanted to know more about event-observer model of Magento.
    Currently I am focussing on sales order placement event. I have created one custom table in Magento that contains different sales order related columns(like increment id from sales_flat_order, item_name,sku from sales_flat_order_item etc.). I connected to mysql database through PHP. I join these table to form a single query & put this query which fetches & inserts data into custom table.
    Now my ultimate aim is, once customer places order, this php file must get called so that all data fetched through that query get inserted into custom table…
    So how event-observer model I can use for the same…do u have any sample code for the same…
    Plz guide me…

    Regards,
    Prat

  13. Hi Tomas,

    Nice post.

    But my requirement is that when user add any product to the cart then sku should be append with product name on all next steps including cart page, checkout page, order, print page etc.
    So If product name is ‘Toys’ and sku is ‘TY12′ then product name should be ‘Toys – TY12′.

    In summary I want to update product name values in order related tables without changing the real name.

    Thanks & Regards,
    Naveen Kumar Jain

  14. Kent K. Yip

    @Naveen Kumar Jain
    you would never use this method to append text to a product listing page or product detail page. you need to go to your phtml that render that text.

    e.g printf(“%s – %s”, $_product->getName(), $_product->getSku());

    your problem is in the frontend, don’t look at a solution for backend. try to keep MVC in mind.

  15. Federer

    Hello, I want to add a event in adminhtml function but the event script never is execute. The config.xml is:

    <admin>
    <events>
    			<sales_order_controller_sendvendors_action>
    	  			<observers>
    	  				<dropshipping_observer>
    						<class>dropshipping/observer</class>
    						<method>sendVendorEmails</method>
    	  				</dropshipping_observer>
    	  			</observers>
    	  		</sales_order_controller_sendvendors_action>
    		</events>
    </admin>
    

    Is correct the xml? Thanks in advanced

  16. Yaroslav

    Hi…great blog and particulary helpfull post. I’ve managed to capture the event and get the request variable. But I want to pass the array to another event, related to an action on the frontend. No matter how hard I try I can not find how. Any suggestion?

  17. Nick

    Code is working great after a few modifications to the naming conventions.

    Now, how would one go about stopping the add to cart action from within the observer? More specifically, the hookToAddToCartBefore method.

    Ideally, I’d like to stop the add to cart, and somehow pass along an event to the page (perhaps via Mage::helper?)

Add Your Comment

Please wrap all source codes with [code][/code] tags.
Top