在我的观察者函数中,我得到了这样的事件传递的变量:

public function observerFunc(Varien_Event_Observer $observer)
{
    $sth = $observer->getEvent()->getSth();
}

如果 sth 是一个对象,我可以通过在其上调用方法来更改它。但是我该如何改变 sth 如果这是一个简单的字符串?我尝试以下没有成功:

public function observerFunc(Varien_Event_Observer $observer)
{
    $sth = $observer->getEvent()->getSth();
    $observer->getEvent()->setSth('test');
    $observer->setSth('test');
}

我刚刚了解到,有些事件也通过了可以更改字符串的传输对象(感谢 亚历克斯),但是事件 page_block_html_topmenu_gethtml_after 才不是。那我该怎么办?

有问题的事件被这样派遣,我想更改$ html:

$html = $this->_getHtml($this->_menu, $childrenWrapClass);
Mage::dispatchEvent('page_block_html_topmenu_gethtml_after', array(
    'menu' => $this->_menu,
    'html' => $html
));
有帮助吗?

解决方案

你不能。

传输对象方法起作用的原因是PHP的对象 是别名/参考. 。修改对象时,您正在修改一个真实的对象。

PHP的原始类型(INT,字符串,布尔值等)不是对象,属于PHP 通过价值通过 参数规则。如果Magento模块开发人员在事件观察者中传递了一个原始字符串

    Mage::dispatchEvent('page_block_html_topmenu_gethtml_after', array(
        'menu' => $this->_menu,
        'html' => $html
    ));

那是他们说的方式

您可以查看此值,但我不希望您修改它。

无论这是故意的设计决定还是开发人员都不将事情作为读者的练习,我们都会离开。

至于您未填写的问题,如果您想修改顶部菜单,我会采用一些方法。钩住 page_block_html_topmenu_gethtml_before 事件并修改 menu 目的

    Mage::dispatchEvent('page_block_html_topmenu_gethtml_before', array(
        'menu' => $this->_menu
    ));

应该工作,因为 _menu 是一个对象

/**
 * Top menu data tree
 *
 * @var Varien_Data_Tree_Node
 */
protected $_menu;

其次,您可以重写菜单生成类

public function getHtml($outermostClass = '', $childrenWrapClass = '')
{
    $html = parent::getHtml($outermostClass, $childrenWrapClass);
    //monkey with $html here to add your menu items or custom markup
    return $html;
}

第三,您可以使用布局更新来删除现有的顶部菜单块,并使用您创建的自定义类插入一个新块。您的自定义类将扩展现有的顶级菜单类,然后重新定义 getHtml. 。这更复杂,但避免了与重写相关的问题。

其他提示

我会说这是该事件的设计错误。

物体通过引用传递,因此可以操纵它们。琴弦总是被复制。因此,在这种情况下,无法在观察者内部操纵字符串 page_block_html_topmenu_gethtml_after 事件在我看来,它的目的是让您有机会操纵 $html.

通过观察到 core_block_abstract_to_html_after 事件 (关联). 。在此事件中,渲染内容将从块实例传输到观察者实例,并且 - 最重要的是,运输的内容是块类返回的内容。请注意,我在示例下方解释了一个重要的缓存考虑。

例子

因为这个事件被解雇了 每一个 块渲染,您应该将观察者配置为单身人士,并测试块类型是 Mage_Page_Block_Html_Topmenu.

public function manipulateTopmenuOutput(Varien_Event_Observer $obs)
{
     if ($obs->getBlock() instanceof Mage_Page_Block_Html_Topmenu){
         $initialOutput = $obs->getTransport()->getHtml();
         //e.g. $modified output = $this->yourManipulationMethod($initialOutput);
         $obs->getTransport()->setHtml($modifiedOutput);
     }
}

您的操作逻辑可以在观察方法中实现,也可以放置在观察者中的另一种方法中。

问题

因为它涉及输出操作 所有块渲染器都会调用观察者,只有在避免块重写的主要问题时才应使用此观察者。 此外,本观察者中生成的内容在 -block_html 缓存写(通过块实例的调用到 _saveCache()),因此您要么需要重新调整 block_html 进入观察者(有点粘,就像您要么使用反射或重复两者的逻辑 _saveCache()_getSidPlaceholder() 编写缓存条目的方法。最后,如果您需要操纵与树节点数据有关的任何内容,则必须生成树节点数据的副本。从理论上讲,这可以通过抓住 Mage_Catalog_Model_Observer 辛格尔顿(Singleton)并从中抓起树...确实很粘。

许可以下: CC-BY-SA归因
scroll top