イベントで渡された文字列を変更するにはどうすればよいですか?
-
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のオブジェクトである エイリアス/参照です. 。オブジェクトを変更すると、1つの真のオブジェクトを変更します。
PHPのプリミティブタイプ(ints、strings、booleansなど)はオブジェクトではなく、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
シングルトンとそれから木をつかむ...本当に粘着性があります。