ฉันจะเปลี่ยนสตริงที่ส่งผ่านเหตุการณ์ได้อย่างไร


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 เป็นนามแฝง / อ้างอิง เมื่อคุณแก้ไขวัตถุคุณกำลังแก้ไข One True Object

ประเภทดั้งเดิมของ PHP (ints, สตริง, 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รายการในผู้สังเกตการณ์อีกครั้งหรือทำซ้ำตรรกะจากทั้ง_saveCache()และ_getSidPlaceholder()วิธีการเขียนรายการแคชและในที่สุดหากคุณต้องการจัดการกับสิ่งที่เกี่ยวข้องกับข้อมูลโหนดต้นไม้คุณจะต้องสร้างสำเนาของข้อมูลโหนดต้นไม้ซึ่งสามารถทำได้ในทางทฤษฎี คว้าตัวMage_Catalog_Model_Observerซิงเกิลและคว้าต้นไม้จากมัน ... เหนียวมากแน่นอน


1
ฉันเกลียดการใช้ TopMenu ของ Magento ด้วยหัวใจที่สำคัญมากของฉัน ฉันกระแทกหัวของฉันเป็นประจำระหว่างการใช้งานใด ๆ ที่ต้องมีการปรับแต่งการนำทาง พวกเขาทำให้มันยากมากที่จะปรับแต่งเอาท์พุท HTML ในลักษณะที่ไม่เป็นการรบกวน วีโอไอพีต่อสู้กับคุณในทุกย่างก้าว
wlvrn

ใช่แล้วเมนูนั้นมีความยืดหยุ่นที่ไม่เหมาะสม แต่คุณจะได้รับฟังก์ชั่นการทำงานที่ใช้งานได้
benmarks
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.