【问题标题】:How do you set the sort order for event observers in Magento?您如何在 Magento 中设置事件观察者的排序顺序?
【发布时间】:2013-04-02 19:23:48
【问题描述】:

我在catalog_product_save_after 事件上创建了一个观察者,但它似乎在运行applyAllRulesOnProduct() 方法的目录规则观察者之前被调用。我需要在applyAllRulesOnProduct() 运行后给我打电话。这些观察者的顺序是如何选择的?

【问题讨论】:

    标签: magento events observers


    【解决方案1】:

    与 Magento 中的许多问题一样,答案很复杂。还有两个可能与您的具体情况有关的问题。这会很长——跳到最后看无上下文的简短版本。

    模块加载顺序

    没有办法明确设置观察者排序顺序。 Magento 将按照它们在merged into the global configuration 的顺序运行这些事件。因此,虽然您无法具体控制事件的顺序,但您可以通过在您的 app/etc/modules XML 声明文件中使用 <depends/> 标记来控制 Magento 加载和合并模块的顺序。 p>

    例如,在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_Api2 中定义的事件将在Mage_CoreMage_Oauth 中定义的事件之后运行。

    缺少&lt;depends/&gt; 节点,模块加载的规则是

    1. 所有核心模块在非核心模块之前加载

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

    让您的模块依赖于Mage_CatalogRule 模块(其中定义了applyAllRulesOnProduct 观察者方法)是一种很好的形式。 但是,这应该不是必需的,因为所有核心模块都在非核心模块之前加载。

    这是因为事件观察者方法的运行顺序还有另一个因素。

    区域顺序

    除了模块顺序之外,您还需要考虑您的事件观察器定义在哪个区域。也就是说,当您在 Magento 中创建事件观察器时,您需要添加一些 @987654340 @ 看起来像这样

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

    在上面的例子中,这个事件观察者被定义在global区域(因为它在&lt;global/&gt;节点内)。这意味着观察者将在 Magento 的frontendadminhtml 区域同时运行。但是,您也可以限制您的事件运行所在的区域。例如,您提到的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(可能还有旧版本)中,来自 &lt;global/&gt; 节点的事件观察者总是在 @987654351 中的事件观察者之前运行@节点。我的猜测是您的事件在 &lt;global/&gt; 节点中。尝试将其移至 &lt;adminhtml/&gt; 节点。

    简短版:确保您的模块&lt;depends/&gt; 位于Mage_CatalogRule 模块上,并将您的事件观察器配置移动到您模块的config.xml 中的&lt;adminhtml/&gt; 节点。

    【讨论】:

    • 感谢您的详细解释;现在很有意义。唯一的调整是使用Mage_CatalogRule(大写“R”)作为&lt;depends/&gt;。现在完美运行。再次感谢!
    • 作为参考,第三个选项可能是:从目录规则中禁用观察者(只需在您的 config.xml 中为该节点设置 type>disabled)并在您自己的内部调用该方法观察者:Mage::getSingleton('catalogrule/observer')->applyAllRulesOnProduct($event);,在你的监听器的开头或结尾(当然取决于你想要什么)
    • 不是对 cme​​ts 部分的适当使用,但我无法抗拒 - 现在进入 Magento 已有近 10 年了,我仍然发现您@AlanStorm 的有用文章。无论是 Magento 1 还是 Magento 2,感谢您对社区的贡献。
    【解决方案2】:

    我知道这是一个旧线程,但如果有人想更改其模块的加载顺序:

    /etc/modules/* 文件夹按字母顺序加载,因此如果您的模块文件位于第一个(或最后一个),它会相应地按该顺序加载 - 因此您可以将 /etc/modules/Namespace_Module.xml 重命名为 /etc /modules/ZZZNamespace_Module.xml 最后加载它(假设没有任何其他带有 ZZZZ 的模块...)

    另外,澄清一下,模块中的所有其他内容都可以保持不变(代码/文件和文件夹名称),您只需更改这个文件,该文件可以任意命名。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-15
      • 1970-01-01
      相关资源
      最近更新 更多