Làm thế nào tôi có thể thay đổi một chuỗi được thông qua bởi một sự kiện?


10

Trong hàm quan sát của tôi, tôi nhận được một biến được truyền bởi sự kiện như thế:

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

Nếu sthlà một đối tượng, tôi có thể thay đổi nó bằng cách gọi các phương thức trên nó. Nhưng làm thế nào tôi có thể thay đổi sthnếu nó là một chuỗi đơn giản? Tôi đã thử những điều sau đây mà không thành công:

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

Tôi mới biết rằng một số sự kiện cũng vượt qua một đối tượng vận chuyển trong đó chuỗi có thể được thay đổi (cảm ơn Alex ), nhưng sự kiện page_block_html_topmenu_gethtml_afterthì không. Vậy tôi có thể làm gì?

Sự kiện trong câu hỏi được gửi đi như thế này và tôi muốn thay đổi $ html:

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

Câu trả lời:


12

Bạn không thể.

Lý do cách tiếp cận đối tượng vận chuyển hoạt động là các đối tượng của PHP là bí danh / tham chiếu . Khi bạn sửa đổi một đối tượng, bạn đang sửa đổi Một đối tượng thật.

Các kiểu nguyên thủy của PHP (ints, chuỗi, booleans, v.v.) không phải là đối tượng và nằm dưới sự vượt qua của PHP bởi các quy tắc giá trị cho các đối số. Nếu nhà phát triển mô-đun Magento chuyển cho bạn một chuỗi thô trong trình quan sát sự kiện

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

đó là cách họ nói

Bạn có thể xem giá trị này, nhưng tôi không muốn bạn sửa đổi nó.

Chúng tôi sẽ để lại cho dù đây là một quyết định thiết kế có chủ ý hay nhà phát triển không nghĩ mọi thứ thông qua như một bài tập cho người đọc.

Đối với câu hỏi không có nội dung của bạn, nếu bạn muốn sửa đổi menu trên cùng, có một vài cách tiếp cận tôi sẽ thực hiện. Móc vào page_block_html_topmenu_gethtml_beforesự kiện và sửa đổi menuđối tượng

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

nên làm việc, vì _menulà một đối tượng

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

Thứ hai, bạn có thể viết lại lớp tạo 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;
}

Thứ ba, bạn có thể sử dụng các cập nhật bố cục để xóa khối menu trên cùng hiện có và chèn một khối mới với một lớp tùy chỉnh bạn đã tạo. Lớp tùy chỉnh của bạn sẽ mở rộng lớp menu trên cùng hiện có, và sau đó xác định lại getHtml. Điều này phức tạp hơn, nhưng tránh được các vấn đề liên quan đến việc viết lại.


5

Tôi sẽ nói rằng đó là một lỗi thiết kế trong sự kiện đó.

Các đối tượng được truyền xung quanh bằng tham chiếu, vì vậy chúng có thể được thao tác. Chuỗi luôn được sao chép. Vì vậy, trong trường hợp này, chuỗi không thể bị thao túng bên trong người quan sát, ngay cả page_block_html_topmenu_gethtml_aftersự kiện chỉ nhìn vào tôi như mục đích của nó là cho bạn cơ hội thao túng $html.


3

có thể sửa đổi đầu ra khối thông qua chuỗi vận chuyển bằng cách quan sát core_block_abstract_to_html_aftersự kiện (liên kết) . Trong trường hợp này, nội dung được kết xuất được vận chuyển từ thể hiện khối sang thể hiện của người quan sát và - quan trọng nhất - nội dung được vận chuyển là nội dung được trả về bởi lớp khối. Lưu ý rằng có một xem xét bộ nhớ đệm quan trọng mà tôi đã giải thích bên dưới ví dụ.

Thí dụ

Vì sự kiện này được kích hoạt cho mọi kết xuất khối, bạn nên định cấu hình người quan sát dưới dạng đơn lẻ và kiểm tra xem loại khối là một thể hiện của 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);
     }
}

Logic thao tác của bạn có thể được thực hiện trong phương pháp quan sát hoặc được đặt trong phương thức khác trong trình quan sát.

Các vấn đề

Bởi vì nó liên quan đến thao tác đầu ra người quan sát được gọi cho tất cả các kết xuất khối, nên điều này chỉ được sử dụng khi mối quan tâm chính là tránh việc viết lại khối. Ngoài ra, nội dung được tạo trong trình quan sát này bị thao túng ghi post- block_htmlcache (thông qua lệnh gọi của thể hiện khối _saveCache()), do đó, bạn sẽ cần phải lưu lại bộ nhớ cache block_htmltrong trình quan sát (một chút dính, vì bạn sẽ sử dụng Reflection hoặc sao chép logic từ cả phương thức _saveCache()_getSidPlaceholder()phương thức để ghi mục nhập bộ đệm. Và cuối cùng, nếu bạn cần thao tác bất cứ điều gì liên quan đến dữ liệu nút cây, bạn sẽ phải tạo một bản sao của dữ liệu nút cây. nắm lấy cây Mage_Catalog_Model_Observerđơn và chộp lấy cái cây từ nó ... thực sự rất dính.


1
Tôi ghét việc triển khai TopMothy của Magento bằng chính bản chất của tâm hồn tôi. Tôi thường xuyên đập đầu vào nó trong bất kỳ triển khai nào yêu cầu tùy chỉnh điều hướng. Họ đã làm cho nó rất khó để điều chỉnh đầu ra HTML theo cách không phô trương; Magento chiến đấu với bạn mỗi bước trên đường.
wlvrn

Vâng, vâng, menu không linh hoạt, nhưng bạn có khá nhiều chức năng hoạt động.
đánh dấu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.