Magento 2: Como alterar o modelo de um bloco sem "nome"


10

Quero alterar para substituir o modelo de um bloco pelo meu modelo personalizado. Mas não tem um "nome", apenas um "como". O que eu quero substituir é:

<block class="Magento\Sales\Block\Adminhtml\Order\View\Items\Renderer\DefaultRenderer"
       as="default"
       template="order/view/items/renderer/default.phtml"/>

Respostas:


8

Como substituir um modelo com layout ALIAS.

Esta resposta é um exemplo possível, você pode seguir isto para substituir o modelo do ALIAS.

Eu criei dois módulos de exemplo, Vendor_Moduletem layout com modelo de alias, estamos substituindo esse alias por Vendortwo_Moduletwomódulo.

Suponha que você saiba as etapas para criar o módulo, não estou postando a criação do módulo inteiro.

Módulo 1

\ app \ code \ Fornecedor \ Módulo \ etc \ frontend \ routes.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="standard">
        <route id="module" frontName="module">
            <module name="Vendor_Module" />
        </route>
    </router>
</config>

\ app \ code \ Vendor \ Module \ view \ frontend \ layout \ module_test_test.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
     <body>     
        <referenceContainer name="content">         
            <block class="Vendor\Module\Block\Test\Test" name="test_test" template="test/test.phtml">
                <block class="Vendor\Module\Block\Test\Test" as="testali" template="test/testali.phtml"/>
            </block>
        </referenceContainer>      
    </body>
</page>

Módulo 2

\ app \ code \ Vendortwo \ Moduletwo \ etc \ frontend \ routes.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="standard">
        <route id="moduletwo" frontName="moduletwo">
            <module name="Vendortwo_Moduletwo" />
        </route>
    </router>
</config>

\ app \ code \ Vendortwo \ Moduletwo \ view \ frontend \ layout \ default.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <referenceBlock name="test_test">
            <block class="Vendortwo\Moduletwo\Block\Two\Two" as="testali" template="two/twoalias.phtml"/>
        </referenceBlock>
</page>

Após remover o cache, executei http: // localhost / magento210 / module / test / test

O modelo de alias é substituído por Vendortwo_Moduletwo two/twoalias.phtml

insira a descrição da imagem aqui


Então, isso está substituindo um bloco por seu apelido? E se eu não quiser substituí-lo, mas adicionar outro bloco depois?
— precisa saber é o seguinte

3

É assim que se faz corretamente e sem hacks.

Não procurei o caso de uso do OP, mas precisava modificar os renderizadores no carrinho. O problema é que, como no caso do OP, o Magento_Checkoutmódulo não fornece nomes para os renderizadores, o que significa que eles não podem ser referenciados e seus modelos alterados usando métodos tradicionais ou documentados. No entanto, após algumas investigações, descobri como fazê-lo usando as ferramentas que o Magento2 nos fornece diretamente no XML do layout.

Observe que existem outros lugares onde essa mesma abordagem funciona, como no Magento\Sales\Block\Items\AbstractItemsbloco. Os módulos Magento_Checkoute Magento_Salessão os dois que mais utilizam os representantes de itens, portanto, isso abrange muitas das consultas que levariam alguém a alterar o modelo de um bloco sem um nome. A razão pela qual isso foi publicado é devido à inevitabilidade de outras pessoas procurarem como modificar modelos de renderizador nos módulos de pagamento ou vendas.

Vou fornecer a solução primeiro e depois explicá-la em detalhes para quem quiser saber por que ela funciona.

Solução

Adicione o seguinte ao checkout_cart_index.xmlarquivo de layout:

<referenceBlock name="checkout.cart.form">
    <arguments>
        <argument name="overridden_templates" xsi:type="array">
            <item name="default" xsi:type="string">LinusShops_Moneymaker::Magento_Checkout/cart/item/default.phtml</item>
            <item name="simple" xsi:type="string">LinusShops_Moneymaker::Magento_Checkout/cart/item/simple.phtml</item>
            <item name="configurable" xsi:type="string">LinusShops_Moneymaker::Magento_Checkout/cart/item/configurable.phtml</item>
        </argument>
    </arguments>
</referenceBlock>

Observe que o nome e o caminho do módulo precisam ser modificados para refletir sua base de código.

Explicação

Isso funciona aproveitando os overridden_templatesdados do bloco, que não são definidos por padrão.

Em Magento_Checkout, o checkout_cart_index.xmlarquivo de layout define o seguinte bloco:

<block class="Magento\Checkout\Block\Cart\Grid" name="checkout.cart.form" as="cart-items" template="cart/form.phtml" after="cart.summary">
    <block class="Magento\Framework\View\Element\RendererList" name="checkout.cart.item.renderers" as="renderer.list"/>
    <block class="Magento\Framework\View\Element\Text\ListText" name="checkout.cart.order.actions"/>
</block>

Em seguida, define alguns desses renderizadores no checkout_cart_item_renderers.xmlarquivo de layout:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="checkout_item_price_renderers"/>
    <body>
        <referenceBlock name="checkout.cart.item.renderers">
            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="default" template="cart/item/default.phtml">
                <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions" name="checkout.cart.item.renderers.default.actions" as="actions">
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Edit" name="checkout.cart.item.renderers.default.actions.edit" template="Magento_Checkout::cart/item/renderer/actions/edit.phtml"/>
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Remove" name="checkout.cart.item.renderers.default.actions.remove" template="Magento_Checkout::cart/item/renderer/actions/remove.phtml"/>
                </block>
            </block>
            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="simple" template="cart/item/default.phtml">
                <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions" name="checkout.cart.item.renderers.simple.actions" as="actions">
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Edit" name="checkout.cart.item.renderers.simple.actions.edit" template="Magento_Checkout::cart/item/renderer/actions/edit.phtml"/>
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Remove" name="checkout.cart.item.renderers.simple.actions.remove" template="Magento_Checkout::cart/item/renderer/actions/remove.phtml"/>
                </block>
            </block>
        </referenceBlock>
    </body>
</page>

Infelizmente, eles não podem ser referenciados por seus aliases defaulte simple, respectivamente.

No entanto, olhando para o Magento\Checkout\Block\Cart\Gridbloco, que é nomeado checkout.cart.forme é o pai dos representantes, pode-se notar que há uma chamada para o getItemHtmlmétodo no modelo associado cart/form.phtml. Esse método então chama getItemRenderer. Ambos os métodos são definidos na Gridclasse pai de AbstractBlock. É aqui que os overridden_templatesdados são usados:

/**
 * Retrieve item renderer block
 *
 * @param string|null $type
 * @return \Magento\Framework\View\Element\Template
 * @throws \RuntimeException
 */
public function getItemRenderer($type = null)
{
    if ($type === null) {
        $type = self::DEFAULT_TYPE;
    }
    $rendererList = $this->_getRendererList();
    if (!$rendererList) {
        throw new \RuntimeException('Renderer list for block "' . $this->getNameInLayout() . '" is not defined');
    }
    $overriddenTemplates = $this->getOverriddenTemplates() ?: [];
    $template = isset($overriddenTemplates[$type]) ? $overriddenTemplates[$type] : $this->getRendererTemplate();
    return $rendererList->getRenderer($type, self::DEFAULT_TYPE, $template);
}

Com esse conhecimento, o preenchimento do bloco com dados do XML de layout é simples, usando a argumentssintaxe do Magento2 .


11
Isso deve ser aceito como a verdadeira solução. Simples e eficaz. Maneira apropriada do Magento2. Ótima explicação. Obrigado!
— Iva

2

Minha solução não é universal, é um "truque sujo", mas pode ser útil em certos casos. Minha amostra é para renderizador de front-end, não para adminhtml (acho que deve ser o mesmo).

Configure o ponto de interrupção \Magento\Framework\Data\Structure::getChildIdcom a condição " $ parentId == 'checkout.cart.item.renderers' " (este é um nome para o bloco pai, como você pode ver no checkout_cart_item_renderers.xmllayout). Todos os blocos filhos têm nomes próprios (computados):

insira a descrição da imagem aqui

Use estes nomes na atualização de layout do seu módulo:

    <referenceBlock name="checkout.cart.item.renderers_schedule_block4">
        <action method="setTemplate">
            <argument name="template" xsi:type="string">Vendor_Module::cart/item/default.phtml</argument>
        </action>
    </referenceBlock>

2
Para quem olha para isso, esteja ciente de que isso vai cair se você apenas der um olhar distante. Não construa sua casa com cartões. Esses números não são garantidos.
— Danemacmillan

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.