如何在Magento 2中覆盖模板

如何在Magento 2中覆盖模板

2016年12月6日发布 in 发展历程
Magento商家需要了解的2017年营业税
Magento商家需要了解的2017年营业税
2016年11月28日
Google宣布“移动优先索引”
Google宣布移动优先索引
2016年12月8日

Magento 2开发人员最常见的任务之一就是覆盖模板。 Magento 2在大多数情况下使此操作变得容易,但是在某些情况下,您会怀疑它是否’甚至可能。本文将介绍在各种情况下适用于替代模板的方法,以及何时应考虑寻求替代替代模板的方法。

在Magento 2中,有两种覆盖模板的主要方法:

  • 主题文件路径
  • 布局块参数

The 模板 path 方法 is used when building a theme and the layout 方法 is used when building a 模组. They are the simplest, most straightforward, and easiest to understand 方法s. 您 will almost always be using 上e of these two 方法s. For the very few times, these two 方法s are not available, you have two other 方法s to choose from:

  • 班级偏好
  • 插入

如果您想避免混乱或信息过多,可以跳过其他两个选项,然后在以后遇到无法用这两种常规方法覆盖的模板时再回来。

主题文件路径

在Magento 2中,主题可以覆盖任何模块’s or parent theme’s layout, 模板, or web (css, js, etc.) file simply by placing it 在 <theme_dir>/<Vendor>_<Module>/path/to/file. For example, If you want to override the 模板 located at <theme_dir>/<Vendor>_<Module>/view/html/header.phtml 对于 the Magento_Theme 模组, you would place your 模板 在 <theme_dir>/Magento_Theme/templates/html/header.phtml.

There are several 块 definitions 在 Magento 2 that do not have the 供应商模块 prefix to specify which 模组 the 模板 belongs to. In these cases, the 块’s 类 attribute will 定义 what 模组 the 模板 belongs to. For example 如果 you were to find a 块 definition 在 the Magento_Checkout 模组 like this you would place your 模板 在 side the Magento_Checkout 模组 directory 在 side your theme.

这个Magento 2 devdoc关于主题继承 详细介绍了如何覆盖主题中的模板。

布局块参数

构建模块时应使用布局方法。要使用布局XML覆盖模板,只需覆盖块’s 模板 论据. Using the 模板 Magento_Wishlist/view/frontend/templates/view.phtml 如 an example, to override view.phtml with your own 模板, you first have to create a new layout file. <Vendor>_<Module>/view/frontend/layout/wishlist_index_index.xml

当前有两种重写block参数的方法。

(新方法)

wishlist_index_index.xml

XHTML
1
2
3
4
5
6
7
8
9
10
<?XML文件 ="1.0"?>
<page XML文件ns:si="http://www.w3.org/2001/XMLSchema-instance" si:noNamespaceSchemaLocation=“ urn:magento:framework:View / Layout / etc / 页_configuration.xsd”>
    <body>
        <referenceBlock 名称=“ customer.wishlist”>
            <arguments>
                <argument 名称=“模板” si:类型=“串”>供应商模块 :: view.phtml</argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

(旧的不赞成使用的方法)

wishlist_index_index.xml

XHTML
1
2
3
4
5
6
7
8
9
10
<?XML文件 ="1.0"?>
<page XML文件ns:si="http://www.w3.org/2001/XMLSchema-instance" si:noNamespaceSchemaLocation=“ urn:magento:framework:View / Layout / etc / 页_configuration.xsd”>
    <body>
        <referenceBlock 名称=“ customer.wishlist”>
            <action 方法=“ setTemplate”>
                <argument 名称=“模板” si:类型=“串”>供应商模块 :: view.phtml</argument>
            </action>
        </referenceBlock>
    </body>
</page>

开发人员说,新方法是用布局XML覆盖模板的适当方法,但根据 问题#3356 在Magento 2 GitHub存储库中,在许多情况下,使用新方法’工作。在这些情况下,可以使用旧的不建议使用的方法,直到问题解决。

现在,您必须将新的自定义模板放置在布局文件中指定的位置。对于此示例,即 <Vendor>_<Module>/view/frontend/templates/view.phtml

只要模块中的模板的路径与您在模板属性中设置的路径相匹配,就无所谓。我喜欢将模板放在您在其原始模块(从模块开始)中找到的相同路径中’的模板目录,但为您的模板的模块名称添加目录’re overriding. For example, 在 your 模组, you would put a wishlist 模板 在 <Vendor>_<Module>/view/frontend/templates/wishlist/view.phtml or 对于 a catalog 模板 it would be <Vendor>_<Module>/view/frontend/template/catalog/view.phtml.

There is 上e additional step 对于 your override to take effect. 您 must add a 顺序 to your 模组.xml file 对于 the 模组 containing the layout file you are modifying. For this example, your etc/module.xml file will look like this.

模组.xml

XHTML
1
2
3
4
5
6
7
8
<?XML文件 ="1.0"?>
<config XML文件ns:si="http://www.w3.org/2001/XMLSchema-instance" si:noNamespaceSchemaLocation=“ urn:magento:framework:Module / etc / 模组.xsd”>
    <module 名称=“供应商模块” setup_version=“ 100.0.0”>
        <sequence>
            <module 名称=“ Magento_Wishlist”/>
        </sequence>
    </module>
</config>

This will ensure that the Magento_Wishlist 模组 will be loaded and added to the merged layout file before your 模组. This is necessary 如 it ensures your 模组’在解析了其所引用的布局XML之后,将解析其Layout覆盖。否则,您的布局可能会引用不’还不存在,因此您的布局覆盖将不适用。

班级偏好

您 may have found that there are some 块 definitions that contain a 模板 attribute but do not contain a 名称 attribute. This means you can’像在模块中通常一样,从布局XML中覆盖该块。如果块’s 模板 attribute does not contain the 供应商模块 prefix you can utilize the 类 偏爱 方法 to override the 模板.

In this example, we will be overriding the 块 containing the cart/item/default.phtml 模板 在 found 在 Magento/Checkout/view/frontend/layout/checkout_cart_item_renderers.xml.

XHTML
1
<block =“ Magento \结帐\块\购物车\商品\渲染器” =“虚拟” 模板=“购物车/商品/default.phtml”>

The 类 attribute 上 the 块 sets the scope 对于 the 模板 path so a 供应商模块 prefix is unnecessary 如果 the 模板 is 在 the same 模组 如 the 块’的班级。这意味着更改模板所需的一切’s模块范围是更改块’像这样在您的di.xml文件中具有类首选项的s类。

di.xml

XHTML
1
2
3
4
<?XML文件 ="1.0"?>
<config XML文件ns:si="http://www.w3.org/2001/XMLSchema-instance" si:noNamespaceSchemaLocation=“ ur:magento:框架:ObjectManager / etc / 配置.xsd”>
    <preference 对于=“ Magento \结帐\块\购物车\商品\渲染器” 类型=“供应商\模块\块\结帐\购物车\项目\渲染器” />
</config>

现在,即使您不这样做,也必须确保该块确实存在’实际上,它不需要做任何事情。为此,您只需创建一个骨架块。

渲染器.php

的PHP
1
2
3
4
5
6
7
8
<?php
/ **
*此块用作更改块定义范围的框架类。
*现在,块上的template属性将默认为该模块,而不是
*核心模块上的原始块定义。
* /
命名空间 供应商\模组\\查看\大车\项目;
渲染器 延伸 \Magento\查看\\大车\项目\渲染器 {}

要完成模板替代,您只需要像从布局中进行常规模板替代一样添加模板即可。在这种情况下,该路径将是 供应商/Module/view/frontend/templates/cart/item/default.phtml

在这一点上,很明显这是一个很大的黑客。仅在极少数情况下谨慎。如果您认为您可能遇到这种情况,请考虑是否有其他选择,例如我将在本文稍后列出的选择。考虑其他模块可能想要执行与您正在执行的操作类似的功能。希望此问题最终得以解决,并且不再需要这种破解。

插入

The 类 偏爱 is an acceptable option when you are wanting to override the 模板 对于 all 在 stances of a 类 and the 供应商_Namespace prefix is missing from the 模板 attribute 上 块 definition. However, there may be times when you need to be more targeted. The 类 may be used 对于 multiple 模板s or the 供应商模块 prefix might be set. In these cases, a 插入 is the best option. For this example we will override Magento_Catalog::category/products.phtml with our own 模板 using a 插入. I won’不会对插件进行详细介绍,如果您不是’还不熟悉它们,请仔细阅读 Magento 2 devdoc插件 在继续之前。

类别视图模板的原始块定义如下所示

XHTML
1
<block =“ Magento \目录\块\类别\视图” 名称=“ category.products” 模板=“ Magento_Catalog :: category / products.phtml”>

So our 插入 will need to hook 在 to the 类 Magento\Catalog\Block\Category\View. The toHtml() 方法, 在 herited by Magento\Framework\View\Element\Template, retrieves the 模板 and turns it 在 to html. To override the 模板 that gets retrieved by that 方法, the $_template 变种iable needs to be changed to your own 模板. Fortunately, the Template 类 already has a 方法 to do that. With this understanding, we can create our 插入 and di.xml files.

di.xml

XHTML
1
2
3
4
5
6
<?XML文件 ="1.0"?>
<config XML文件ns:si="http://www.w3.org/2001/XMLSchema-instance" si:noNamespaceSchemaLocation=“ ur:magento:框架:ObjectManager / etc / 配置.xsd”>
    <type 名称=“ Magento \目录\块\类别\视图”>
        <plugin 名称=“ 模组_catalog_category_view_override_template” 类型=“供应商\模块\插件\目录\块\类别\视图” />
    </type>
</config>

视图.php

的PHP
1
2
3
4
5
6
7
8
9
10
11
12
<?php
命名空间 供应商\模组\插入\目录\\类别;
 
视图
{
    上市 功能 beforeToHtml(\Magento\目录\\类别\视图 $ subject)
    {
        如果 ($范本 === 'Magento_Catalog :: category / products.phtml') {
            $ subject->setTemplate('供应商_>模块:: catalog / category / products.phtml');
        }
    }
}

The 插入 could be set 上 a few other 方法s but I chose toHtml because it is the 方法 在 which the 模板 is first used. This 方法 of overriding a 模板 is not recommended except when necessary. It should 上ly be used 如果 the 块 does not have a 名称, has a 供应商模块 prefix and/or has a 类 that handles multiple 模板s. To complete the 模板 override just place your 模板 在 your 模组 在 the appropriate location,<Vendor>/<Module>/view/frontend/templates/catalog/category/products.phtml

您应该使用哪种方法?

没有一种特定的方法应在所有情况下使用。如果要构建主题,请使用模板路径方法。如果要构建模块,请使用布局方法。对于试图找出核心Magento模板已被覆盖的开发人员,这是他们将要寻找的两个地方。如果正在构建模块,并且遇到无法按名称引用的块,则可以使用两种非常规方法之一来覆盖该块’s 模板.

备择方案

要修改页面上的某些内容,覆盖模板并不总是最好的选择。另一个模块可以使用这四种方法中的任何一种来覆盖您的替代,块的名称可以通过更新来更改,或者分配给块的类可以更改。当然,在很多情况下,它是最好的,即使不是唯一的选择。但是,在某些情况下,最好走另一条路线。

布局结构允许插入子块

Many times, the 上ly change required to a 模板 is an addition to the beginning or end of that 模板. In these cases, 如果 the 块 defining the 模板 you want to override is nested 在 side a container, you can simply create your own 块 and place it before or 后 the 块 you previously wanted to override. One of the distinguishing characteristics between 块s and containers is that children of 块s must be explicitly called 在 order to be rendered while children of containers will render all of their children 块s and containers. So all that is required to add your new markup to the wishlist 页 is to create your own layout/wishlist_index_index.xml file, like this:

XHTML
1
2
3
4
5
6
7
8
<?XML文件 ="1.0"?>
<page XML文件ns:si="http://www.w3.org/2001/XMLSchema-instance" si:noNamespaceSchemaLocation=“ urn:magento:framework:View / Layout / etc / 页_configuration.xsd”>
    <body>
        <referenceContainer 名称=“内容”>
            <block =“ Magento \框架\视图\元素\模板” 名称=“ some.block” 模板=“ 供应商模块 :: some-template.phtml” =“ customer.wishlist”/>
        </referenceContainer>
    </body>
</page>

您 上ly need to remove an element

这不是’建议使用,但对于确实要避免覆盖模板删除元素的情况,可以使用JS或CSS删除元素。它’从易于实现的角度考虑,这是一个好主意,但通常不是最佳解决方案。如果使用得太频繁,您可能会载入大量HTML内容,但’t显示给用户。这会增加页面加载时间,并导致混乱且难以维护的HTML和CSS。确实没有明确的界限“too frequent”因此,除非绝对必要,否则最好避免使用此选项。

您 need to replace a jQuery 小部件 with your own

在Magento 2中覆盖JS不会 ’t always require overriding the 模板 where it gets 在 itialized. 您 can override 功能s and objects 上 a jQuery UI 小部件 much like you would override a 变种iable or 方法 上 a 的PHP 类 you are extending. To do this, first create your JS file 在 your theme or 模组:

  • 主题: <Vendor>/<Theme>/web/js/customAccordion.js
  • 模块: <Vendor>/<Module>/view/frontend/web/js/customAccordion.js

customAccordion.js

的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
定义([
  'jquery',
  'jquery / ui',
  '法师/手风琴'
], 功能($){
  $.小部件('供应商_Module.customAccordion', $.法师.手风琴, {
      _创建: 功能() {
          //这里的自定义代码
      }
  });
 
  返回 $.供应商模块.customAccordion;
});

现在为您的customAccordion小部件创建一个映射:

  • 主题: <Vendor>/<Theme>/requirejs-config.js
  • 模块: <Vendor>/<Module>/view/frontend/requirejs-config.js

requirejs-config.js

的JavaScript
1
2
3
4
5
6
7
变种 配置 = {
    地图: {
        '*': {
            '手风琴': '供应商_Module/js/customAccordion'
        }
    }
};

现在,包括或初始化手风琴的任何地方,都将加载您的自定义手风琴。想要查询更多的信息。查看此Magento 2 devdoc: 自定义默认的Magento jQuery小部件

您 want to change a line of text

Magento 2 has a very easy 方法 of overriding strings of text. 您 can do this by adding a translation to your theme or 模组 that matches the line of text you want to change and replaces it with any string you set. This approach isn’虽然这被认为是最佳实践,但有时值得进行权衡,而不必覆盖大型模板以进行简单的文本更改。要了解更多信息,请阅读Magento 2 devdocs上的本指南: 使用翻译词典自定义字符串. 您 need to be careful when using this 方法 在 case a string you’重新翻译用于多个位置。

包起来

您’我们了解了Magento 2模板替代的好,坏和丑陋。覆盖模板的两种主要方法是“good”,但并非总是必要的。他们俩“bad”几乎不需要覆写模板的方法,即使这样,也应将其视为一种hack,在可能的情况下需要对其进行替换。模板替代是在Magento 2中进行更改的一种快速简便的方法,它们很容易被滥用。如果有选择,请考虑替代模板的替代方法。

9 评论

  1. 萨雅拉杰 说:

    你好

    我是Magneto2的新手。我想禁用magento2模板中的响应视图。我能怎么做…

  2. 杜申乔希 说:

    不错的教程。这是否适用于/兼容Magento 2.1.X?

    谢谢

  3. 亚历克斯 说:

    嗨,弥敦道,

    感谢您分享这篇文章,我一直在寻找有关主题文件路径和布局XML文件的帮助,以向magento模块添加自定义信息,您的文章对我添加帖子主题路径也有很大帮助,我发现了这篇文章, //www.cloudways.com/blog/customize-magento-modules-through-layout-xml-files/ ,希望这对大家有帮助,并继续发布更多信息,我将继续跟进。

  4. 法师情人 说:

    你好

    感谢分享。这里 ’是我找到的另一本指南,它也是一个有用的指南: //magenticians.com/magento-2-override-block/

  5. 鲁迪爵士 说:

    I’d阅读了大约十二本有关为Magento 2创建自定义主题的教程。但这是第一本全面介绍该主题的教程。– 谢谢!

  6. 法师情人 说:

    你好,

    感谢您分享这个很棒的教程。在研究过程中,我发现了另一本有关Magneto 2布局,模板,块的出色指南。这里是: //magenticians.com/using-magento-2-blocks-layouts-templates/

    希望它能帮助您的读者更多ðŸ™,

  7. 塔拉 说:

    很棒的教程….thanks a ton!!!

发表评论

您r email address will not be published. 必需的地方已做标记 *

该网站使用Akismet减少垃圾邮件。 了解如何处理您的评论数据.

最近的帖子查看全部
2020年10月22日
通过 阿什莉·科利弗 商业见解, 优雅的骆马 2020年10月22日
毫无疑问,2020年是历史性的一年。火灾,全球大流行,暴动,老虎王等’只是冰山一角。如 [â€]