Choosing a right event to observe

havana.club

When you develop your Magento module or any kind of modification by observing events, it is very important to choose proper events to observe.
One method is to search Magento core files in your PHP IDE for “Mage::dispatchEvent(“, which should result with about 400 occurrences. Many of those method calls pass a static string as event name, e.g.

Mage::dispatchEvent('catalog_product_is_salable_before', array('product' => $this));

There are also event calls where event name is generated by concatenating some variable to a static string, like

Mage::dispatchEvent($this->_eventPrefix.'_validate_before', array($this->_eventObject=>$this));

In those cases we can’t be sure which would be the final event name. Since Magento doesn’t allow us to observe more than one event at the same time, we should find way to get all events for certain request.
If we check Mage::dispatchEvent declaration in app/Mage.php we would see the following:

public static function dispatchEvent($name, array $data = array())
    {
        Varien_Profiler::start('DISPATCH EVENT:'.$name);
        $result = self::app()->dispatchEvent($name, $data);
        #$result = self::registry('events')->dispatch($name, $data);
        Varien_Profiler::stop('DISPATCH EVENT:'.$name);
        return $result;
    }

We can’t rewrite Mage class to add the functionality for event name catching. The Mage::dispatchEvent method calls dispatchEvent method from Mage_Core_Model_App. We can’t rewrite Mage_Core_Model_App niether, because the app object is instantiated directly, not from Mage::getModel factory method. So, the only way to get all event names for certain request is to add a single hard-coded line in Mage::dispatchEvent method.
We can add something like following:

Mage::log($name, null, 'events.log', true);

That logs the name of each event dispatched in request.
After modification, dispatchEvent method in app/Mage.php should look like:

public static function dispatchEvent($name, array $data = array())
    {
        // log event name
        Mage::log($name, null, 'events.log', true);
 
        Varien_Profiler::start('DISPATCH EVENT:'.$name);
        $result = self::app()->dispatchEvent($name, $data);
        #$result = self::registry('events')->dispatch($name, $data);
        Varien_Profiler::stop('DISPATCH EVENT:'.$name);
        return $result;
    }

Cheers !

Interested in hiring us?

Have a chat with us. You would be surprised how small changes can make your business even more successful.


15 comments

  1. when i chaged the function in app/Mage.php as given below
    public static function dispatchEvent($name, array $data = array())
    {
    // log event name
    Mage::log($name, null, ‘events.log’, true);

    Varien_Profiler::start(‘DISPATCH EVENT:’.$name);
    $result = self::app()->dispatchEvent($name, $data);
    #$result = self::registry(‘events’)->dispatch($name, $data);
    Varien_Profiler::stop(‘DISPATCH EVENT:’.$name);
    return $result;
    }
    the following errror appears

    Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 79 bytes) in D:\xampp\htdocs\magento8\lib\Zend\Log.php on line 268
    How can i correct this problem
    Thank you for your time
    shakeel ur rehman

  2. That should read ‘I put the observer under global … events tags (in config.xml)
    Thanks in advance!

  3. Love your tutorials guys.

    I set up an observer for checkout_submit_all_after which works fine via the frontend but won’t catch the event when it is fired over SOAP. I put the observer under so it should be capturing it.

    I followed your advice and logged calls to dispatchEvent, and I can see the event is definitely firing, but I can’t catch it. Any ideas?

  4. I figured out my problem. In order for me to get every event listed, I had to enable System > Configuration > Advanced > Developer > Log Settings > Enable Logging.

    With it disabled, I would only see the 3 events above.

  5. I did this, but the only events I see in my log are:
    resource_get_tablename
    core_collection_abstract_load_before
    and core_collection_abstract_load_after.

    Nothing else shows up. Is this right?

  6. @Pavel

    Zvonimir in time of writing this article was working with Magento for about less than 10 days. It’s really promising from him to become realy great Magento developer because he realized how to see all events of one action in such a short period of time.
    Additionally he wanted to see all events and chose appropriate one for his task as the title of this post says.
    He’s concern wasn’t about performance gains or such that you might think of, but just merely to see all events that he can hook on.

    @Zvonimir
    Congrats Zvone on your first Havana post :)

  7. Event Observers are quite nice, very powerful and easy to use.
    But a lot of extension developers forget to set the “event prefix” for their models, so e.g. only Model_Save_After is fired. Therefor you need to rewrite the Extension Model for changes.

    Same Problem in Backend or Adminhtml Module of Magento. Blocks at Backend only fires core_block_abstract_prepare_layout_before, and if you need Mage_Adminhtml_Block_Sales_Order_Grid your Observer ist called 10 times before (and called on every Pageview in Backend) you find the right Block and do some layout changes without a rewrite. Another Problem herein is getting the right block. This only works as long as no other module rewrites this block.
    Why the Sales Order Grid can’t fire adminhtml_block_sales_order_grid_prepare_layout_before? Its very long of cause, but it is fired only once and proof against rewrites.

    I don’t want to rewrite the Sales Order Grid for just adding a new Massaction or a new Grid Column or adding a fancy action button.

    Or is there another possibility?

  8. In Version 1.7.0.2 this change breaks the save function of products (at least on a completely fresh installation).

  9. This is the only comprehensive method I’ve found for getting events. It’s verbose and obtuse in the output, but “by cracky” you’re going to get them all. The next step usually is to find out what objects get passed so you can then start using the event to do something.

    In my case, it also pointed out that there was no event that came close to doing what I wanted, so I created one to pass the order quote object so I could extract cart contents for abandoned cart management for guest customers.

  10. Congratulations Zvonimir for your 1st post. Keep them coming…
    Btw. Information to the readers: If you were wondering why there is a “Havana Club” image attached to this post, the reason is that Zvonimir joined a Havana Team.

  11. @Pavel
    Thank you for your comment.
    There are many events that are not visible in profiler. Try to compare profiler output with events.log.

    @Simon
    That’s just a list of events, that doesn’t guarantee that event has been dispached.

  12. You can enable profiler to get list of events. Check records “DISPATCH EVENT:” from Mage::dispatchEvent() and “OBSERVER:” from Mage_Core_Model_App::dispatchEvent()

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.