如何更改事件传递的字符串?
-
16-10-2019 - |
题
在我的观察者函数中,我得到了这样的事件传递的变量:
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)并从中抓起树...确实很粘。