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