Question

Dans ma fonction d'observateur, je reçois une variable passée par l'événement comme ça:

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

Si sth est un objet, je peux le modifier en appelant des méthodes sur elle. Mais comment puis-je changerai sth si elle est une chaîne simple? J'ai essayé ce qui suit sans succès:

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

Je viens d'apprendre que certains événements passent également un objet de transport dans lequel la chaîne peut être modifiée (merci Alex ), mais le page_block_html_topmenu_gethtml_after de l'événement ne fonctionne pas. Que puis-je faire?

L'événement en question se dépêcha comme ça et je veux modifier $ html:

$html = $this->_getHtml($this->_menu, $childrenWrapClass);
Mage::dispatchEvent('page_block_html_topmenu_gethtml_after', array(
    'menu' => $this->_menu,
    'html' => $html
));
Était-ce utile?

La solution

Vous ne pouvez pas.

La raison pour laquelle l'approche objet fonctionne de transport est des objets PHP sont des alias / références . Lorsque vous modifiez un objet, vous modifiez le seul vrai objet.

types primitifs de PHP (ints, chaînes, booléens, etc.) ne sont pas des objets, et tombent sous PHP passer de par valeur des règles pour les arguments. Si un développeur de modules Magento vous transmet une chaîne brute dans un observateur d'événements

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

qui est leur façon de dire

  

Vous pouvez regarder cette valeur, mais je ne veux pas que vous le modifier.

Nous allons laisser que ce soit une décision délibérée de conception ou d'un développeur ne pas penser les choses à travers comme un exercice pour le lecteur.

Quant à votre question posée, si vous souhaitez modifier le menu principal, il y a quelques approches que je prendrais. Raccordement en cas de page_block_html_topmenu_gethtml_before et modifier l'objet de menu

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

devrait fonctionner, puisque _menu est un objet

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

En second lieu, vous pouvez réécrire la classe de génération de 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;
}

Troisièmement, vous pouvez utiliser la mise en page des mises à jour pour supprimer le bloc de menu principal existant et insérer un nouveau bloc avec une classe personnalisée que vous avez créé. Vous classe personnalisée étendez la classe supérieure de menu existant, puis Redéfinir getHtml. Ceci est plus compliqué, mais évite les problèmes liés à réécritures.

Autres conseils

Je dirais que c'est un bug de conception dans cet événement.

Les objets se passe autour par référence, afin qu'ils puissent être manipulés. Les chaînes sont copiés toujours. Donc, dans ce cas, la chaîne ne peut pas être manipulé à l'intérieur de l'observateur, même l'événement page_block_html_topmenu_gethtml_after semble juste pour moi comme son but est de vous donner une chance de manipuler le $html.

possible de modifier la sortie du bloc par l'intermédiaire de chaîne transporté par l'observation de l'événement core_block_abstract_to_html_after (lien) . Dans ce cas, le contenu rendu est transporté de l'instance de bloc à l'instance d'observateur, et - le plus important - le contenu transporté est ce qui est renvoyé par la classe de bloc. Notez qu'il ya une considération importante de la mise en cache que je l'ai expliqué ci-dessous l'exemple.

Exemple

Parce que cet événement est déclenché pour tous bloc render, vous devez configurer l'observateur comme un singleton et vérifiez que le type de bloc est une instance de 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);
     }
}

Votre logique de manipulation peut être mis en oeuvre dans le procédé d'observation ou placé dans un autre procédé dans l'observateur.

Questions

Parce qu'il implique la manipulation de sortie et l'observateur est appelé à tout bloc rend, cela ne devrait être utilisée que lorsque la principale préoccupation est d'éviter une ré-écriture de bloc. Aussi , la le contenu généré dans cet observateur est manipulé écriture de cache post-block_html (via l'appel de l'instance de bloc à _saveCache()), de sorte que vous soit besoin de re-cache l'entrée de block_html dans l'observateur (un collant bits, comme vous souhaitez soit utiliser la réflexion ou dupliquer la logique à la fois des _saveCache() et des méthodes _getSidPlaceholder() pour écrire l'entrée du cache. et enfin, si vous avez besoin de manipuler tout ce qui concerne les données de nœud d'arbre, vous devez générer une copie des données de nœud d'arbre. Cela pourrait théoriquement être fait en saisissant le singleton Mage_Catalog_Model_Observer et saisissant l'arbre d'elle ... très collante en effet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top