在Magento中,您如何设置事件观察者的排序顺序?

14
我在catalog_product_save_after事件上创建了一个观察者,但它似乎在运行applyAllRulesOnProduct()方法的catalogrule观察者之前被调用。我需要在applyAllRulesOnProduct()运行后调用我的观察者。这些观察者的顺序是如何选择的?
2个回答

36

答案像Magento中的许多问题一样复杂。您的特定情况可能涉及到两个可能的问题。这将会很长 - 跳到结尾获取无上下文的简短版本。

模块加载顺序

没有办法明确地设置观察者的排序顺序。Magento将按照它们合并到全局配置中的顺序运行事件。因此,虽然您无法特别控制事件的顺序,但是您可以通过在app/etc/modules XML声明文件中使用<depends/>标记来控制Magento加载和合并模块的顺序。

例如,在Mage_Api2.xml文件中:

<!-- 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>

作者表示,Mage_Api2 模块 依赖于 Mage_CoreMage_Oauth 模块。这意味着 Mage_Api2config.xml 文件将在 Mage_CoreMage_Oauthconfig.xml 文件之后合并。这意味着在 Mage_CoreMage_Oauth 中定义的事件之后,将运行在 Mage_Api2 中定义的事件。
缺少<depends/>节点,在模块加载的规则中有以下:
  1. 所有核心模块在非核心模块之前加载

  2. 其余模块按字母顺序加载。

最好让您的模块依赖于 Mage_CatalogRule 模块(其中定义了 applyAllRulesOnProduct 观察者方法)。然而,这不是必需的,因为所有核心模块都在非核心模块之前加载。
因为订单事件观察方法运行顺序中还有另一个因素。
区域顺序
除了模块顺序,您还需要考虑事件观察器定义的区域。也就是说,当您在Magento中创建事件观察器时,会放置一些类似于config.xml的内容。
<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>

在上面的例子中,这个事件观察者已经在“全局”区域中定义(因为它在“”节点内部)。这意味着观察者将在Magento的“frontend”和“adminhtml”区域中运行。但是,也有可能限制事件运行的区域。例如,你提到的“catalogrule”事件是在“adminhtml”区域中定义的。
<!-- #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>

这意味着这个事件观察者只会在Magento的后端adminhtml区域运行。换句话说,它仅在您在后端管理控制台保存事件时运行。

就是我认为您的问题所在,因为在现代版本的Magento(可能还包括旧版本),<global/>节点中的事件观察者总是在<adminhtml/>节点中的事件观察者之前运行。我的猜测是您的事件在<global/>节点中。尝试将其移动到<adminhtml/>节点。

简短版:确保您的模块<depends/>Mage_CatalogRule模块,并将事件观察者配置移动到您的模块的config.xml中的<adminhtml/>节点。


非常感谢您的详细解释,现在我完全明白了。唯一需要调整的是在<depends/>中使用Mage_CatalogRule(大写“R”)。现在它完美地工作了。再次感谢! - Scruffy Paws
3
作为参考,第三种选项可能是:禁用目录规则的观察者(只需在config.xml中为该节点设置type>disabled</type),并在您自己的观察者中调用该方法:Mage::getSingleton('catalogrule/observer')->applyAllRulesOnProduct($event);,在侦听器的开头或结尾调用该方法(当然取决于您想要什么)。 - Enrique
1
这不是评论区的适当用法,但我忍不住要说——现在已经接近10年的Magento历程中,我仍然从您@AlanStorm的有益文章中发现了很多帮助。无论是Magento 1还是Magento 2,感谢您为社区做出的贡献。 - Darren Felton

3

我知道这是一个旧的帖子,但如果有人想要改变他们模块的加载顺序:

/etc/modules/* 文件夹按字母顺序加载,所以如果你的模块文件排在第一位(或最后一位),它会相应地按照那个顺序加载- 所以你可以将 /etc/modules/Namespace_Module.xml 重命名为 /etc/modules/ZZZNamespace_Module.xml,以便它最后被加载(假设没有其他以 ZZZZ... 开头的模块)

另外,需要澄清的是,你模块中的其他所有内容都可以保持不变(代码/文件和文件夹名称),你只需要更改这个文件的名称,它可以被命名为任何你选择的名称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接