ลบบล็อกจากเลย์เอาต์ที่ไม่มีชื่อ


12

ฉันต้องการลบบล็อกออกจากเลย์เอาต์ใน magento 2 ที่มีการประกาศในส่วนขยายของบุคคลที่สาม แต่บล็อกนั้นไม่มีชื่อ
ฉันจะทำสิ่งนั้นได้ไหม

บล็อกถูกประกาศเช่นนี้

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

ฉันไม่สามารถใช้

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

เพราะอย่างที่คุณเห็นไม่มีชื่อเลย


marius ฉันมีความคิดถ้าเราใช้เหตุการณ์และลบบล็อกด้วยชื่อเทมเพลตการจับคู่ [Vendor_Module]::template.phtml
Amit Bera

ฉันมีความคิดเดียวกัน (ดูความเห็นเกี่ยวกับคำตอบ) แต่ฉันจะใช้มันเป็นเพียงมาตรการที่สิ้นหวัง ฉันหวังว่าจะได้คำตอบง่ายๆ หากคุณมีรหัสให้โพสต์เป็นคำตอบ
Marius

ฮ่า ๆ ๆ ที่เรา donot มีทางออกง่าย ๆ ลองดูคำตอบโดยใช้เหตุการณ์
Amit Bera

คำตอบ:


5

ฉันพบปัญหานี้ในชั้นเรียน Magento\Framework\View\Layout\ScheduledStructure\Helper

มีฟังก์ชั่น_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++;
}

มันถูกเรียกจากscheduleStructureฟังก์ชั่น:

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

ด้วยกรณีนี้ชื่อบล็อกสามารถ:

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

ฉันคิดว่าคุณควรกำหนดบล็อกผลรวมโดยไม่มีชื่อบนคอนเทนเนอร์และชื่อบล็อกคำสั่งซื้อจำเป็นต้องลบออกในคอนเทนเนอร์


ฉันไม่คิดว่ามันจะใช้ได้ ไม่มีทางที่จะคาดเดาชื่อที่สร้างขึ้นได้เนื่องจากในหน้าต่างๆสามารถมีหลายบล็อคที่เพิ่มในbody.before.endคอนเทนเนอร์ตามลำดับที่แตกต่างกัน
Marius

กรณีนี้ใช้กับบล็อก / คอนเทนเนอร์ที่ไม่มีชื่อเท่านั้น หากพวกเขาทั้งหมดไม่มีชื่อยากที่จะกำหนดบล็อก / ภาชนะบางอย่างต้องเอาออก
ท้าวผาม

อ๋อ ... ปัญหาของฉันอย่างแน่นอน
Marius

เราควรเขียนใหม่$name = $this->_generateAnonymousName($parentNode->getElementName() . '_schedule_block');ควรผ่านคลาส & แม่แบบไปยังพารามิเตอร์หรือไม่
ท้าว Pham

2
ดูเหมือนว่าจะมีค่าใช้จ่ายในการเขียนบางอย่างเช่นนั้น ฉันกำลังมองหาวิธีแก้ปัญหาอย่างง่าย ๆ (ถ้ามี) หรือคำตอบเช่น 'ไม่สามารถทำได้ง่ายมาก' ฉันคิดว่าฉันสามารถสังเกตรูปแบบการสร้างบล็อกเหตุการณ์หรือบางสิ่งบางอย่างเพื่อลบมันที่นั่น แต่ดูเหมือนว่าค่าใช้จ่ายมากเกินไปอีกครั้ง ฉันเก็บมันไว้เป็นโซลูชั่นสำรอง
Marius

3

ฉันให้ความคิดที่ไม่ดีกับคุณจริงๆ

นี่เป็นแนวคิดที่ไม่ได้หยุดเอาท์พุทบล็อกของคุณ

ใช้เหตุการณ์ 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>

และการใช้ผู้สังเกตการณ์นี้จะปิดการใช้งานผลลัพธ์ของบล็อกของคุณ

<?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('');

    }
  }
}

นี่ไม่ใช่ความคิดที่เลวร้ายจริงๆ อันที่จริงมี overkill สังเกตบล็อคทั้งหมด แต่ฉันยินดีที่จะใช้มันมากกว่าตัวเลือกอื่น ๆ ฉันจะพยายามและแจ้งให้คุณทราบ
Marius

coool มนุษย์ .... ดูว่าเกิดอะไรขึ้น
Amit Bera

1
ใช้งานได้ แต่ฉันพยายามปรับให้เหมาะสมเล็กน้อยเพื่อไม่ให้เรียกใช้โค้ดสำหรับทุกบล็อค ดังนั้นผมจึงจบลงด้วยคำตอบของฉัน ขอบคุณสำหรับความคิด
Marius

ฉันเห็นคำตอบว่าเป็นคนดีจริงๆ :)
Amit Bera

3

ฉันได้รับแนวคิดจากคำตอบของ Amitและจบลงด้วยวิธีแก้ปัญหาการทำงานที่ไม่ได้ดูน่ารำคาญและไม่เกินความเป็นจริงเพราะรหัสของฉันถูกเรียกใช้เพียงครั้งเดียว

ฉันได้สร้างผู้สังเกตการณ์ในเหตุการณ์layout_generate_blocks_afterที่ดำเนินการหลังจากที่โหลดเลย์เอาท์และบล็อกถูกสร้างขึ้นแล้ว

สิ่งนี้อาจมีข้อเสียเปรียบเนื่องจากบล็อกที่ฉันพยายามลบยังคงได้รับอินสแตนซ์ แต่ในกรณีของฉันฉันต้องลบออกจากหน้าเว็บ

ดังนั้นฉันมีไฟล์ 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>

และชั้นผู้สังเกตการณ์ของฉัน:

<?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);
            }
        }
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.