Php Magento:如何禁用或更改核心观察者方法的工作方式

Php Magento:如何禁用或更改核心观察者方法的工作方式,php,magento,observer-pattern,Php,Magento,Observer Pattern,我想知道这件事已经有一段时间了。如果Magento编写了一个核心观察者类并执行了一个您不希望它执行的功能,或者您想重写它,该怎么办?有没有办法说,不要在观察者身上使用这种方法,只使用我的方法。如果我为我自己的观察者设置了一个方法,它会不会先做核心功能,然后再做我已经实现的任何事情 例如,Magento希望用Observer方法将一些数据保存到数据库中,但我根本不希望它保存这些数据,我想让它保存一些我为数据库添加了列或属性的其他数据。关于类重写是实现自己功能的最后手段的标准警告 也许可以随意加载M

我想知道这件事已经有一段时间了。如果Magento编写了一个核心观察者类并执行了一个您不希望它执行的功能,或者您想重写它,该怎么办?有没有办法说,不要在观察者身上使用这种方法,只使用我的方法。如果我为我自己的观察者设置了一个方法,它会不会先做核心功能,然后再做我已经实现的任何事情


例如,Magento希望用Observer方法将一些数据保存到数据库中,但我根本不希望它保存这些数据,我想让它保存一些我为数据库添加了列或属性的其他数据。

关于类重写是实现自己功能的最后手段的标准警告

也许可以随意加载Magento全局配置来删除核心Magento观察器,但是没有支持的方法

但是,请考虑核心观察器是如何配置的。

<adminhtml>
    <events>
        <cms_wysiwyg_config_prepare>
            <observers>
                <widget_observer>
                    <class>widget/observer</class>
                    <method>prepareWidgetsPluginConfig</method>
                </widget_observer>
            </observers>
        </cms_wysiwyg_config_prepare>
    </events>
</adminhtml>

小部件/观察者
准备好图中的DGETS插件
观察员是Magento模型类。如果已使用基于URI/路径的语法配置模型

<class>widget/observer</class>
widget/observer
而不是完整的PHP类名

<class>Mage_Widget_Model_Observer</class>
Mage\u Widget\u Model\u Observer
您可以为观察者模型类创建替代(就像您可以为任何其他模型创建替代一样)。如果使用了一个PHP类名,那么您就不走运了。(如果愿意承担维护责任,可以将本地文件放在local/Mage/Widget/Model/Observer.php中,但我不建议这样做)

因此,要覆盖上述观察者,您需要

  • 创建一个自定义模块,其中包含一个类Mage_Widget_Model_Observer的覆盖

  • 在override类中,要么重新声明
    prepareWidgetSpluginFig
    以执行所需操作,要么重写特定方法。这可能包括一个空方法来完全删除该功能


  • 我想在@Alan的回答中添加一条评论,因为我认为他已经做到了,但我的评论太长,格式不够!下面是:

    很好的一个@Alan,这是一个聪明的方法,可以修复看起来像是一个洞的东西,同时仍然尊重建筑。有几点想法:

  • 如果自定义模块绑定到同一事件,则在职责链中调用自定义观察者的时间将晚于核心,因此可能会覆盖核心观察者?这取决于核心观察者正在做什么,例如设置重定向值。在OP提供的示例中,这将起作用。当绑定到Model_save_before事件时,将调用核心观察者,但您的观察者仍可以在将模型保存数据写入数据库之前修改其内容。您可以更改或取消设置受核心观察者影响的值

  • 要覆盖核心观察者的模型,在config.xml中插入
    将是正确的方法

  • 这可能是重写(!)时不需要调用
    parent::
    的少数情况之一

  • 嗯,, 法学博士


    编辑-在步骤1中添加了更多信息以回答OP问题的细节

    谢谢Jonathan,我用基本模型覆盖语法覆盖了Observer

    <config>
         <global>
            <models>
                <sales>
                    <rewrite>
                        <observer>PPI_Sales_Model_Observer</observer>
                    </rewrite>
               </sales>
            </models>
        </global>
    </config>
    
    
    PPI_销售_模型_观察员
    

    它工作得很好。

    更好的方法是在config.xml文件中重新声明观察者的定义

    例如,我需要禁用在事件controller\u action\u layout\u generate\u blocks\u之后通过模块enterprise\u persistent声明的enterprise\u persistent\u cart观察者

    Enterprise_Persistent的config.xml文件中的声明如下

    <frontend>
        <events>
            <controller_action_layout_generate_blocks_after>
                <observers>
                    <enterprise_persistent_cart>
                        <class>enterprise_persistent/observer</class>
                        <method>removeCartLink</method>
                    </enterprise_persistent_cart>
                </observers>
           </controller_action_layout_generate_blocks_after>
    
    
    企业/观察员
    removeCartLink
    
    因此,我创建了一个模块,并在模块的config.xml中执行以下操作:

    <frontend>
        <events>
            <controller_action_layout_generate_blocks_after>
                <observers>
                    <enterprise_persistent_cart>
                        <type>disabled</type>
                    </enterprise_persistent_cart>
                </observers>
            </controller_action_layout_generate_blocks_after>
    
    
    残废
    
    我还使我的模块依赖于Enterprise_持久化模块。这对于确保在Enterprise_持久化模块的config.xml之后处理模块的config.xml是必需的。为此,我在模块的app/etc/modules my_module.xml模块声明文件中执行了以下操作

    <config>
        <modules>
            <Atlex_AddCartLinkToHeader>
                <active>true</active>
                <codePool>local</codePool>
                <depends>
                    <Enterprise_Persistent/>
                </depends>
            </Atlex_AddCartLinkToHeader>
        </modules>
    </config>
    
    
    真的
    地方的
    
    对于每个事件,对于给定的观察者名称,只能声明一个观察者操作。因此,只要我的模块的config.xml是在Enterprise_Persistent模块的config.xml文件之后处理的,我对Enterprise_Persistent_cart的观察者声明将是执行的观察者操作

    禁用的节点将禁用观察者触发。如果您想覆盖观测者来执行您自己的方法,那么您只需将节点替换为观测者的和节点即可


    这允许您在不重写核心类的情况下重写/禁用观察者。对于未来的开发人员来说,它更具可扩展性。

    非常感谢Alan,我在想您必须能够重写它,但找不到任何人谈论这样做。这是我一直困扰的一件事。我确实在lib目录的Event.php中找到了removeObserverByName($observerName),但不确定如何使用它。我喜欢你的方法,早上我会试试,让你知道它是如何工作的。谢谢乔纳森,我真的很感激你,李