名前のないレイアウトからブロックを削除する


12

サードパーティの拡張機能で宣言されているmagento 2のレイアウトからブロックを削除したいのですが、ブロックに名前がありません。
それをしてもいいですか?

ブロックは次のように宣言されています

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

使えない

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

ご覧のとおり、名前はありません。


マリウスは、私はidea.if我々は試合テンプレート名でイベントやリムーブブロック使用してい [Vendor_Module]::template.phtml
アミットベラ

私は同じ考えを持っています(回答のコメントを参照)が、私はそれを必死の手段としてのみ使用します。私は簡単な解決策を望んでいました。コードがある場合は、回答として投稿してください。
マリウス

簡単な解決策はありません。イベントを使用して答えを出してみましょう
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
  • ...

コンテナーの名前なしでtotalsブロックを定義し、コンテナーの注文ブロック名を削除する必要があると思います。


これでうまくいくとは思いません。異なるページでは、body.before.endコンテナに複数のブロックが異なる順序で追加される可能性があるため、生成された名前を予測する方法はありません。
マリウス

このケースは、名前のないブロック/コンテナーにのみ適用されます。名前のないすべての場合、いくつかのブロック/コンテナを定義するのは難しいので、削除する必要があります。
Thao Pham 2017

うん...私の問題は正確に
マリウス

私たちは、書き換える必要があり$name = $this->_generateAnonymousName($parentNode->getElementName() . '_schedule_block');、パラメータにパスクラス&テンプレートべきか?
Thao Pham

2
そのようなものを書き換えるオーバーヘッドのようです。簡単な解決策(ある場合)または「非常に簡単にはできない」などの答えを探しています。レイアウト生成ブロックイベントまたはそれを削除する何かを観察できると思いますが、やはりオーバーヘッドが多すぎるようです。私はそれをバックアップソリューションとして保持しています。
マリウス

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

    }
  }
}

これは実際にはそれほど悪い考えではありません。確かに、すべてのブロックを監視するやり過ぎがありますが、私は他のオプションの上でそれを使用したいと思っています。お知らせします。
マリウス

クール。男....何が起こるかを見てください
アミットベラ

1
機能しますが、すべてのブロックのコードを実行するのではなく、少し最適化しようとしました。だから私は私の答えで終わった。アイデアをありがとう。
マリウス

私は答えを見る、その本当に良い男:)
アミットベラ

3

私はアミットの答えからアイデアを得て、コードが一度しか実行されないため、あまり邪魔にならず、やり過ぎではない実用的なソリューションになりました。

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.