Magento 2: Zmiana szablonu bloku

52

W Magento 1, jako programista modułów, można zmienić szablon bloku za pomocą kodu XML układu podobnego do tego

<reference name="block_to_change">
    <action method="setTemplate">
        <param>/path/to/template.phtml</param>
    </action>
</reference>

a następnie dodając szablon do motywu podstawowego.

app/design/frontend/base/default/template/path/to/template.phtml

Czy jako programista modułów można zrobić coś podobnego w Magento 2? Czy też muszę użyć kodu XML układu lub PHP, aby usunąć interesujący mnie blok i wstawić nowy blok z innym szablonem (którego klasa rozszerza klasę oryginalnego bloku)

Wiem, że mogę utworzyć niestandardową kompozycję, która zastępuje szablon, ale jestem zainteresowany stworzeniem modułu, który zmienia domyślny szablon, ale nadal pozwala niestandardowej kompozycji na zastąpienie tego szablonu.

Alan Storm
źródło

Odpowiedzi:

59

Oczywiście możliwe jest:

<referenceBlock name="copyright">
    <action method="setTemplate">
        <argument name="template" xsi:type="string">Dfr_Backend::page/copyright.phtml</argument>
    </action>
</referenceBlock>
Mage2.PRO
źródło
Czy możesz wyjaśnić, w jaki sposób mogę zmienić układ, w rzeczywistości chcę zaktualizować plik add to addtocart.phtml zgodnie z konfiguracją systemu, a także chcę to zaktualizować za pomocą niestandardowego modułu
Deepak Mankotia
5
Rozwiązanie KAndy nie działało dla mnie, ale jedno tak
csmarvz
Zmieniłem szablon nazwy bloku „klient_konto_konto_podkładu” <body> <referencja Nazwa bloku = „klient_konto_konto_kopii”> <metoda działania = „setTemplate”> <nazwa argumentu = "szablon" xsi: type = "string"> Namespace_Modulename :: zamówienie /recentorder.phtml </argument> </action> </referenceBlock> </body> "ale to nie działa, uprzejmie sprawdź i daj mi znać swoje komentarze
sentil
43

Węzeł akcji jest przestarzały, ale można użyć argumentów blokowych

<referenceBlock name="block_to_change">
    <arguments>
        <argument name="template" xsi:type="string">[Vendor]_[Module]::/path/to/template.phtml</argument>
    </arguments>
</referenceBlock>
KAndy
źródło
Czy możesz wyjaśnić, w jaki sposób mogę zmienić układ, w rzeczywistości chcę zaktualizować dodatek do addtocart.phtmlpliku zgodnie z konfiguracją systemu, a także chcę to zaktualizować za pomocą niestandardowego modułu
Deepak Mankotia
4
Dzięki - zostawię tutaj odniesienie do raportu o błędzie github.com/magento/magento2/issues/3356 - metoda opublikowana w tej odpowiedzi, choć prawdopodobnie przyszły sposób robienia rzeczy, nie działa jeszcze tak, jak reklamowano
Kristof o Fooman
2
@KAndy Czy Twój przykładowy kod jest w 100% poprawny? Próbowałem tego i nie mogę zmusić go do działania w jakikolwiek sposób. Inna odpowiedź z @ Mage2.PRO (która używa <action method='setTemplate'>) działa bez problemów.
maginfortis
1
To nie działa Zaakceptowana odpowiedź jednak.
Milan Simek,
29

Aby zrozumieć różnicę między <arguments>i <action>musisz zrozumieć, jak konstruktorzy Magento 2 obiektów działać. Jeśli przesłonisz konstruktor w Magento, zawsze otrzymasz $data-parametertablicę, która jest tablicą. Są to dane przewidziane w plikach XML i tłumaczona na wewnętrzny $_data-arrayz \Magento\Framework\DataObject:

<referenceBlock name="catalog.topnav">
    <arguments>
        <argument name="template" xsi:type="string">Foo_Bar::buzz.phtml</argument>
    </arguments>
</referenceBlock>    

...

public function __construct(array $data = [])
{
    // $_data is populated with the arguments from XML:
    // so $_data['template'] is now 'Foo_Bar::buzz.phtml'
    $this->_data = $data;
}

Jednak w przypadku szablonu, jeśli setTemplate()jest używany w pseudo-konstruktorze ( _construct()pojedynczy podkreślnik), oznacza to, że $datajest on zastępowany, bez względu na to, czy jest ustawiony w XML.

public function _construct()
{
    $this->setTemplate('foo/bar.phtml');
}

W tym scenariuszu <action>jest preferowany, ponieważ jest on wykonywany po konstruktorze i pseudo-konstruktorze.

<referenceBlock name="catalog.topnav">
    <action method="setTemplate">
        <argument name="template" xsi:type="string">Foo_Bar::buzz.phtml</argument>
    </action>
</referenceBlock> 
Giel Berkers
źródło
10

Poniższe działało dla mnie w Magento EE 2.2.3

<?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">
    <body>
        <referenceBlock name="core.module.block.name" template="[Vendor]_[Module]::path/to/your/template.phtml" />
    </body>
</page>

Uwaga: jeśli używasz niestandardowego modułu do zmiany szablonu rdzenia i oszalejesz, ponieważ poprzedni wycinek kodu nie działa, upewnij się, że moduł jest ładowany po module rdzenia, który próbujesz zmienić (module.xml), a ty wykonane bin/magento setup:upgrade:)

diazwatson
źródło
To moim zdaniem najczystszy sposób.
Ben Crook,
2

Nie wiem dlaczego, ale uważam, że ten sposób jest najlepszy:

<referenceBlock name="sales.order.items.renderers.default" template="Foo_Bar::sales/order/items/renderer/default.phtml"/>
Aivoris
źródło
1
<referenceBlock name="sales.order.items.renderers.default" template="Foo_Bar::sales/order/items/renderer/default.phtml"/>

Działa to tylko wtedy, gdy twój blok nie został nadpisany przed użyciem setTemplatemetody. Magento 2.2.xi wyższe.

AleksLi
źródło