Codegento Who Let Mage Out Of The Cage?

4Apr/1115

Observers and Dispatching Events

As stated in many previous posts, it is not a wise idea to modify core code. There are basically three ways to extend/change the behavior of Magento and since copying Mage files down into the local code pool is the last resort, and we have already talked about rewriting, I thought I would try my hand at explaining the Event Dispatching/Observer system.

What is this Event Dispatching system I speak of?

Magento has picked places in their code where they feel people might want to extend the functionality of the core. In those places, they "dispatch an event" and pass along any objects that might be related to that event. You can assign a function(s) to "listen" to these events and in the functions you can act upon the objects that are passed in.

For instance, if you needed to send some order information to another system after an order has been placed, you could rewrite Mage_Checkout_Model_Type_Onepage's saveOrder() function and add the necessary code, but you will quickly find out that there are other models that you would have to alter as well. If you look closely at that function, at the end you will find:

        Mage::dispatchEvent(
            'checkout_submit_all_after',
            array('order' => $order, 'quote' => $this->getQuote(), 'recurring_profiles' => $profiles)
        );

This gives us the opportunity to act on the order (or quote, or recurring profile) object in a completely "decoupled" way. Not only that, but this same event is fired at the end of every checkout, so you only have to have your code in ONE place.

So how do you hook into this event that is dispatched?

  1. Create a new Model. This model doesn't need to extend anything specific and to be honest, most "observer models" don't extend anything.
  2. Create a new function in the new model. This function should be public and take in a variable called $observer (actually, it can be called anything, but convention calls it $observer)
  3. Register this model/function to be called when the event is dispatched. Below is an example of how do do that.
  4. Clear the cache.
<global>
	<events>
		<checkout_submit_all_after>
		    <observers>
		        <awesome_example>
		            <type>singleton</type>
		            <class>awesome/observer</class>
		            <method>doSomething</method>
		        </awesome_example>
		    </observers>
		</checkout_submit_all_after>
   	</events>
</global>
  • <global> - If you want your observer to listen no matter where the event is dispatched from, put it here. You can also put it in "frontend" or "adminhtml".
  • <events> - This is the element that stores all of the events that are registered.
  • <checkout_submit_all_after> - This is the "event" that you are listening to.
  • <observers> - This is the type of event. I don't think there are others.
  • <awesome_example> - This is a unique string that defines this configuration. It can be anything, and just needs to be unique.
  • <type> - I have always used singleton, but other options can be "model" or "object". The "singleton" will create the object as Mage::getSingleton() while both "object" and "model" will use Mage::getModel() when creating the observer object.
  • <class> - This is the observer class.
  • <method> - This is the function to be called in the observer class.

Here is the contents of our observer model:

<?php

class Super_Awesome_Model_Observer
{
	public function doSomething($observer){
		if (isset($observer['orders'])) {
			$orders = $observer['orders'];
			foreach ($orders as $order) {
				//Do something with the order
			}
		} else {
			//Do something with the order
		}
	}
}

Because the $observer variable can be anything and contain anything we have to make sure our method can handle what is being passed in. In this case it can either have "orders" or "order" passed in, depending on what checkout you go through.

So now, when you go through ANY checkout, this observer will be used to do something with your order(s).

What happens when you have multiple observers listening to the same event?

That is a fun problem. You can affect the order of your observers by implementing the element in your module config, but this might become tricky to remember/maintain. If you can, you should code your observers as if there are ASYNCHRONOUS even though they are SYNCHRONOUS.

Example: If I have two modules (Super_Awesome and Super_Rad) that both listen to the "controller_action_predispatch" event. Super_Awesome will be dispatched to first because it will be loaded in the config first by alphabetical order. However, if I make Super_Awesome "depend" on Super_Rad, Super_Rad will be loaded into the config first and it's observer will be used before Super_Awesome's.

Can you do anything else with the event observers?

This event dispatching stuff shouldn't only be for the Mage team to implement. In any of your development, consider using this pattern to make your code cleaner and more maintainable/extendable.

Also, check out MageDev's blog to find out how to Add Event Observers On The Fly.

Happy Observing!

Posted by Ben Robie

Comments (15) Trackbacks (0)
  1. Nice article – I have an observer listening to checkout_onepage_controller_success_action and checkout_multishipping_controller_success_action, but what I can’t figure out is how to then have my observer ‘inject’ a bit of html into the success page after a customer has placed an order. Every tutorial I’ve found online (including yours) indicates to “do something” inside the code, but how can i have the observer do something that is then rendered later in the page? If I echo anything in the observer method it of course it just output before the start of the html doc. Thanks.

  2. HI Ben,
    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

  3. Great article. One of the better ones to put this magento functionality into perspective. I’m currently developing my first Magento module thats functionlity will be based around an observer event. Basically when the order has gone through and payment has been confirmed, I want to look at the order with after the apporopriate event fires, then look specifically for a product attribute. I will then post to a custom table with this modified data. So basically a separate record for that specific ordered item will be made. Now my question is, what is the best event to listen for to ensure payment had gone through? I am using magento 1.6.2 and will always be using one page checkout. I’ve seen three events that might work, ‘sales_order_invoice_pay’, ‘checkout_submit_all_after’, ‘checkout_type_onepage_save_order_after’. Anyone know the best event to use? Thanks

  4. Hi Ben,

    I have been working on and off with Magento so I’m just trying to brush up on it for starting a new project and I was pointed in the direction of observers where I would have normally have just gone down the route of rewriting as you referred to in your previous article.

    It’s great you’ve gone to a bit more detail and explained the configuration a bit more than other examples out there. The XML configuration files and figuring out how to piece them together is not my strongest point so this really helps, especially highlighting the fact that can be anything as long as it’s unique. Too many articles just seem to paste a sample configuration with little or no explanation and expect you to know what’s set in stone and what you make up as you go along which isn’t ideal for those who aren’t confident with the configuration files yet.

    Anyway, this has put me off to a great start with magento observers.

    Many thanks.

    Chris.

  5. i get following error
    Warning: include(Mage\Atoz\Model\Observer.php) failed to open stream: No such file or directory in E:\wamp\www\lb\lib\Varien\Autoload.php on line 93

    i dont know why its including “Mage\Atoz\Model\Observer.php” , Atoz is located in app\code\local\Muq
    any help?

  6. i want to know what’s different from override

  7. Awsome article bravo!.. excellent in magento

  8. Hi! Thanks for the great article, it is very useful information, our team has an article on the similar topic posted here http://www.atwix.com/magento/observers-reality-or-fiction/ you’re welcome to check it out and leave your feedback

  9. Hopefully Magento won’t change this in the next version! Like their (un)famous template change within the 1.X version that required a complete rewrite of the templates if you want to upgrade to the latest version…

  10. Nice post help me a lot.For code coverage this guy has some example code
    http://www.techflirt.com/magento-event-observer-hook-in-magento/ .you may refer for code here

  11. A motivating discussion is definitely worth comment. I do believe that you ought to write more on
    this subject, it might not be a taboo matter but generally people
    don’t discuss such topics. To the next! Kind regards!!

  12. <?php
     
    class Super_Awesome_Model_Observer
    {
        public function doSomething($observer){
            if (isset($observer['orders'])) {
                $orders = $observer['orders'];
                foreach ($orders as $order) {
                    //Do something with the order
                }
            } else {
                //Do something with the order
            }
        }
    }

  13. Topical medications vary, and can include antibiotic creams that reduce the swelling
    and rosy color of rosacea. If the first round is not completely effective, wait and then try
    a second. Author is an online medical researcher on natural acne treatment and skin care.

  14. On remarque tout de suite que vous maîtrisez superbement bien ce que vous
    dites

  15. WOԜ just what I was searching for. Came here by searching foг city home


Leave a comment

(required)

Trackbacks are disabled.