Як я можу змінити рядок, переданий подією?


10

У своїй функції спостереження я отримую змінну, передану подібно до такої події:

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
));

Відповіді:


12

Ви не можете.

Причиною, що працює підходом до транспортного об'єкта, є об'єкти PHP - псевдоніми / посилання . Коли ви змінюєте об'єкт, ви змінюєте Єдиний істинний об'єкт.

Примітивні типи PHP (ints, string, 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. Це складніше, але дозволяє уникнути проблем, пов’язаних із переписуваннями.


5

Я б сказав, що це помилка дизайну в тому випадку.

Об'єкти обходять посиланням, тому ними можна маніпулювати. Рядки завжди копіюються. Тож у цьому випадку струною не можна маніпулювати всередині спостерігача, навіть page_block_html_topmenu_gethtml_afterподія просто здається мені такою, що її мета - дати вам шанс маніпулювати $html.


3

Це є можливим змінити вихід блоку з допомогою переміщуваної рядки, спостерігаючи 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запис у спостерігачі (трохи клейкий, як ви б або використовували Reflection або дублювання логіки як із методів, так _saveCache()і _getSidPlaceholder()методів написання запису кешу. І нарешті, якщо вам потрібно маніпулювати чим-небудь, що стосується даних вузла дерева, вам доведеться генерувати копію даних вузла дерева. Теоретично це може зробити схопивши Mage_Catalog_Model_Observerодинака і схопивши дерево з нього ... дійсно дуже липко.


1
Я ненавиджу реалізацію TopMenu Magento із самою сутністю моєї душі. Я звичайно нахиляю собі голову під час будь-якої реалізації, яка потребує налаштування навігації. Вони зробили надзвичайно складно налаштувати цей вихід HTML ненав'язливо; Magento бореться з вами на кожному кроці.
wlvrn

Ну, так, меню є неналежно негнучким, але ви маєте дуже багато функціональності, який працює.
орієнтири
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.