Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you set the sort order for event observers in Magento?

I have created an observer on the catalog_product_save_after event, but it seems to be getting called before the catalogrule observer that runs the applyAllRulesOnProduct() method. I need to call mine after applyAllRulesOnProduct() runs. How is the order for these observers chosen?

like image 703
Scruffy Paws Avatar asked Apr 10 '13 19:04

Scruffy Paws


People also ask

In which order the observers will get executed which are listening to the same event?

Observer will be executed in all areas: adminhtml , crontab , frontend , graphql , webapi_rest , webapi_soap . Observer will be executed in the adminhtml area only. Observer will be executed in the crontab area only.

How do you call observer function in Magento 2?

Use the dispatch method of the \Magento\Framework\Event\ Manager class to call an event. In this example, we called 2 events: "my_module_event_before" and "my_module_event_after". Observers should join the events by such names.

What is difference between plugin and observer in Magento 2?

Observers are less versatile than plugins. Plugins can alter the functionality of any Magento public method (except for virtual and final classes, final, static and non-public methods, constructors, and objects instantiated before bootstrapping Magento\Framework\Interception).


2 Answers

The answer, like many in Magento, is complicated. There's also two possible problems your specific situation might relate to. This is going to be long — skip to the end for the contextless short version.

Module Loading Order

There is not way to explicitly set an observer sort order. Magento will run through the events in the order they've been merged into the global configuration. So, while you can't control the order of event specifically, you can control the order Magento loads and merges modules in by using the <depends/> tag in your app/etc/modules XML declaration file.

For example, in the Mage_Api2.xml file

<!-- File: app/etc/modules/Mage_Api2.xml -->
<config>
    <modules>
        <Mage_Api2>
            <active>true</active>
            <codePool>core</codePool>
            <depends>
                <Mage_Core />
                <Mage_Oauth />
            </depends>
        </Mage_Api2>
    </modules>
</config>

the author has indicated that the Mage_Api2 module depends on the Mage_Core and Mage_Oauth modules. This means Mage_Api2's config.xml file will be merged after the config.xml files of Mage_Core and Mage_Oauth. This means that events defined in Mage_Api2 will run after events defined in Mage_Core and Mage_Oauth.

Lacking a <depends/> node, the rules for module loading are

  1. All core modules are loaded before non-core modules

  2. The remaining modules are loaded alphabetically.

It would be good form to have your module depend on the Mage_CatalogRule module (where the applyAllRulesOnProduct observer method is defined). However, it should not be necessary, as all core modules are loaded before non-core modules.

That's because there's another factor in the order event observer methods are run in.

Area Order

In addition to module order, you'll also need to consider which area your event observer is defined in. That is, when you create an event observer in Magento, you drop in some config.xml that looks like this

<config>
    <!-- ... -->
    <global>
        <!-- ... -->
        <events>
            <catalog_product_save_after>
                <observers>
                    <abc_abc>
                        <class>abc_abc/observer</class>
                        <method>test</method>
                    </abc_abc>
                </observers>
            </catalog_product_save_after>
        </events>       
    </global>
</config>

In the above example, this event observer has been defined in the global area (because it's inside the <global/> node). This means the observer will run in both the frontend and adminhtml areas of Magento. However, it's also possible to restrict the area your event is run in. For example, the catalogrule event you mentioned is defined in the adminhtml area

<!-- #File: app/code/core/Mage/CatalogRule/etc/config.xml -->
<config>
    <!-- ... -->
    <adminhtml>
        <!-- ... -->
        <events>
            <!-- ... -->
            <catalog_product_save_after>
                <observers>
                    <catalogrule>
                        <class>catalogrule/observer</class>
                        <method>applyAllRulesOnProduct</method>
                    </catalogrule>
                </observers>
            </catalog_product_save_after>
        </events>
    </adminhtml>
</config>

This means this event observer will only run in Magento's backend adminhtml area. In other words, it only runs when you save an event in the backend admin console.

This is where I think your problem is, because in modern versions of Magento (and possibly the old ones), event observers from the <global/> node always run before event observers in the <adminhtml/> node. My guess is your event is in the <global/> node. Try moving it to the <adminhtml/> node.

The Short Version: Make sure your module <depends/> on the Mage_CatalogRule module, and move your event observer configuration to the <adminhtml/> node in your module's config.xml.

like image 52
Alan Storm Avatar answered Nov 08 '22 18:11

Alan Storm


I know this is an old thread, but in case anyone wants to change the load order of their module:

The /etc/modules/* folder is loaded alphabetically, so if your module's file comes first (or last) it is loaded in that order accordingly- So you could just rename /etc/modules/Namespace_Module.xml to /etc/modules/ZZZNamespace_Module.xml to have it loaded last (assuming there aren't any other modules with ZZZZ...)

Also, to clarify, everything else in your module can remain intact (code/file and folder names), you would just change this one file which can be named anything you choose.

like image 42
Jeff Lenz Avatar answered Nov 08 '22 19:11

Jeff Lenz