Как я могу изменить строку, пройденную событием?

magento.stackexchange https://magento.stackexchange.com/questions/634

  •  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
));
Это было полезно?

Решение

Вы не можете.

Причина, по которой работает подход Transport Object, - это объекты 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 мероприятие (ссылка на сайт). Анкет В этом случае визуализированный контент транспортируется из экземпляра блока в экземпляр Observer, и, что наиболее важно, транспортируемый контент - это то, что возвращается классом блока. Обратите внимание, что существует важное рассмотрение кэширования, которое я объяснил ниже примера.

Пример

Потому что это событие уволено для каждый рендеринг блока, вы должны настроить наблюдателя в качестве синглтона и проверить, что тип блока является экземпляром 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 Синглтон и схватить дерево с него ... действительно очень липкий.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с magento.stackexchange
scroll top