Xóa một khối khỏi bố cục mà không có tên


11

Tôi muốn xóa một khối khỏi bố cục trong magento 2 được khai báo trong phần mở rộng của bên thứ ba, nhưng khối đó không có tên.
Tôi có thể làm điều đó?

Khối được khai báo như thế này

<referenceContainer name="before.body.end">
    <block class="Magento\Backend\Block\Template" template="[Vendor_Module]::template.phtml"/>
</referenceContainer>

Tôi không thể sử dụng

<referenceBlock name="..." remove="true" /> 

bởi vì, như bạn có thể thấy không có tên trên đó.


marius, tôi có ý tưởng. Nếu chúng tôi sử dụng sự kiện và xóa khối theo tên mẫu phù hợp [Vendor_Module]::template.phtml
Amit Bera

Tôi có cùng một ý tưởng (xem bình luận về câu trả lời) nhưng tôi sẽ chỉ sử dụng nó như một biện pháp tuyệt vọng. Tôi đã hy vọng cho một giải pháp đơn giản. Nếu bạn có một số mã, gửi nó như là một câu trả lời.
Marius

ha ha mà chúng tôi không có giải pháp đơn giản. Hãy thử cho tôi một câu trả lời bằng cách sử dụng sự kiện
Amit Bera

Câu trả lời:


5

Tôi thấy vấn đề này trong lớp Magento\Framework\View\Layout\ScheduledStructure\Helper

Có chức năng _generateAnonymousName:

protected function _generateAnonymousName($class)
{
    $position = strpos($class, '\\Block\\');
    $key = $position !== false ? substr($class, $position + 7) : $class;
    $key = strtolower(trim($key, '_'));
    return $key . $this->counter++;
}

Đó là cuộc gọi từ scheduleStructurechức năng:

    public function scheduleStructure(
    Layout\ScheduledStructure $scheduledStructure,
    Layout\Element $currentNode,
    Layout\Element $parentNode
) {
    // if it hasn't a name it must be generated
    if (!(string)$currentNode->getAttribute('name')) {
        $name = $this->_generateAnonymousName($parentNode->getElementName() . '_schedule_block'); // CALL HERE
        $currentNode->setAttribute('name', $name);
    }
    $path = $name = (string)$currentNode->getAttribute('name');

    // Prepare scheduled element with default parameters [type, alias, parentName, siblingName, isAfter]
    $row = [
        self::SCHEDULED_STRUCTURE_INDEX_TYPE           => $currentNode->getName(),
        self::SCHEDULED_STRUCTURE_INDEX_ALIAS          => '',
        self::SCHEDULED_STRUCTURE_INDEX_PARENT_NAME    => '',
        self::SCHEDULED_STRUCTURE_INDEX_SIBLING_NAME   => null,
        self::SCHEDULED_STRUCTURE_INDEX_IS_AFTER       => true,
    ];

    $parentName = $parentNode->getElementName();
    //if this element has a parent element, there must be reset [alias, parentName, siblingName, isAfter]
    if ($parentName) {
        $row[self::SCHEDULED_STRUCTURE_INDEX_ALIAS] = (string)$currentNode->getAttribute('as');
        $row[self::SCHEDULED_STRUCTURE_INDEX_PARENT_NAME] = $parentName;

        list($row[self::SCHEDULED_STRUCTURE_INDEX_SIBLING_NAME],
            $row[self::SCHEDULED_STRUCTURE_INDEX_IS_AFTER]) = $this->_beforeAfterToSibling($currentNode);

        // materialized path for referencing nodes in the plain array of _scheduledStructure
        if ($scheduledStructure->hasPath($parentName)) {
            $path = $scheduledStructure->getPath($parentName) . '/' . $path;
        }
    }

    $this->_overrideElementWorkaround($scheduledStructure, $name, $path);
    $scheduledStructure->setPathElement($name, $path);
    $scheduledStructure->setStructureElement($name, $row);
    return $name;
}

Trong trường hợp này, tên Khối có thể là:

  • before.body.end_schedule_block1
  • before.body.end_schedule_block2
  • ...

Tôi nghĩ bạn nên xác định khối tổng mà không có tên trên container và tên khối thứ tự cần xóa trên container.


Tôi không nghĩ rằng điều này sẽ làm việc. Không có cách nào để dự đoán tên được tạo vì trên các trang khác nhau có thể có nhiều khối được thêm vào trong body.before.endthùng theo thứ tự khác nhau.
Marius

Trường hợp này chỉ áp dụng cho khối / container không có tên. Nếu tất cả chúng không có tên, rất khó để xác định một số khối / container cần loại bỏ.
Thảo Phạm

vâng ... vấn đề của tôi chính xác
Marius

Chúng ta nên viết lại $name = $this->_generateAnonymousName($parentNode->getElementName() . '_schedule_block');, Có nên chuyển lớp & mẫu cho tham số?
Thảo Phạm

2
có vẻ như một chi phí để viết lại một cái gì đó như thế Tôi đang tìm kiếm một giải pháp đơn giản (nếu có) hoặc một câu trả lời như 'không thể thực hiện được một cách dễ dàng'. Tôi nghĩ rằng tôi có thể quan sát sự kiện tạo khối bố trí hoặc một cái gì đó để loại bỏ nó ở đó, nhưng một lần nữa dường như quá nhiều chi phí. Tôi đang giữ đó là một giải pháp dự phòng.
Marius

2

Tôi thực sự cho bạn ý tưởng tồi.

Ở đây ý tưởng không dừng đầu ra của khối của bạn

Sử dụng sự kiện view_block_abstract_to_html_after

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="view_block_abstract_to_html_after">
        <observer name="myObserverName" instance="Stack\Work\Observer\MyObserver" />
    </event>
</config>

Và sử dụng trình quan sát này sẽ vô hiệu hóa đầu ra của khối của bạn

<?php
namespace Stack\Work\Observer;
use Magento\Framework\Event\ObserverInterface;

class MyObserver implements ObserverInterface
{
  public function __construct()
  {
    //Observer initialization code...
    //You can use dependency injection to get any class this observer may need.
  }

  public function execute(\Magento\Framework\Event\Observer $observer)
  {
    $block = $observer->getData('block');

    if('[Vendor_Module]::template.phtml' == $block->getTemplate()){
        $transport = $observer->getData('transport');
        $transport->setHtml('');

    }
  }
}

Đây thực sự không phải là một ý tưởng tồi. Thật vậy, có một sự quá mức khi quan sát tất cả các khối, nhưng tôi sẵn sàng sử dụng nó hơn các lựa chọn khác. Tôi sẽ cố gắng và cho bạn biết.
Marius

coool. người đàn ông .... xem những gì xảy ra
Amit Bera

1
Nó hoạt động, nhưng tôi đã cố gắng tối ưu hóa nó một chút, không thực thi mã cho mọi khối. Vì vậy, tôi đã kết thúc với câu trả lời của tôi . Cảm ơn ý kiến.
Marius

Tôi thấy câu trả lời, người đàn ông thực sự tốt đó :)
Amit Bera

2

Tôi đã có một ý tưởng từ câu trả lời của Amit và kết thúc với một giải pháp hoạt động trông không bị xâm phạm và nó không phải là quá mức vì mã của tôi chỉ được thực thi một lần.

Tôi đã tạo một người quan sát về sự kiện layout_generate_blocks_afterđược thực hiện sau khi bố trí được tải và các khối được tạo.

Điều này có thể có một nhược điểm vì khối tôi đang cố xóa vẫn bị khởi tạo, nhưng trong trường hợp của tôi, tôi chỉ cần xóa nó khỏi trang.

Vì vậy, tôi có tập tin etc/adminhtml/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="layout_generate_blocks_after">
        <observer name="remove-the-block" instance="[MyVendor]\[MyModule]\Observer\RemoveBlock" />
    </event>
</config>

và lớp người quan sát của tôi:

<?php
namespace [MyVendor]\[MyModule]\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class RemoveBlock implements ObserverInterface
{
    const TEMPLATE_TO_REMOVE = '[OtherVendor]_[OtherModule]::template.phtml';
    public function execute(Observer $observer)
    {
        /** @var \Magento\Framework\View\Layout $layout */
        $layout = $observer->getLayout();
        $blocks = $layout->getAllBlocks();
        foreach ($blocks as $key => $block) {
            /** @var \Magento\Framework\View\Element\Template $block */
            if ($block->getTemplate() == self::TEMPLATE_TO_REMOVE) {
                $layout->unsetElement($key);
            }
        }
    }
}
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.