玛托托 2开发人员最常见的任务之一是覆盖模板。 Magento 2在大多数情况下使这很容易,但有一些情况会让你想知道它是否’甚至可能。本文将涵盖哪种方法覆盖模板的各种情况适用于各种情况,并且当您考虑追求模板覆盖时的替代品。
在Magento 2中,有两种主要方法覆盖模板:
在构建主题时使用模板路径方法,并且在构建模块时使用布局方法。它们是最简单,最简单,最简单的方法。您几乎总是使用这两种方法之一。在几次,这两种方法不可用,您还有另外两种方法可以选择:
如果您希望避免混淆或信息过载,则可以跳过其他两个选项是可以接受的,然后在将来恢复到您无法使用两个传统方法中覆盖的模板时。
在Magento 2中,主题可以覆盖任何模块’s or parent theme’s layout, template, or web (css, js, etc.) file simply by placing it in <theme_dir>/<Vendor>_<Module>/path/to/file
. For example, If you want to override the template located at <theme_dir>/<Vendor>_<Module>/view/html/header.phtml
为了 the 玛托托_Theme
module, you would place your template in <theme_dir>/Magento_Theme/templates/html/header.phtml
.
There are several block definitions in Magento 2 that do not have the 小贩_Module.
prefix to specify which module the template belongs to. In these cases, the block’s class attribute will define what module the template belongs to. For example if you were to find a block definition in the 玛托托_Checkout
模块 like this
you would place your template inside the 玛托托_Checkout
模块 directory inside your theme.
这个Magento 2 devdoc主题继承 有关如何在主题中覆盖模板的详细信息。
构建模块时应使用布局方法。要使用布局XML覆盖模板,只需覆盖块’s template argument. Using the template 玛托托_Wishlist/view/frontend/templates/view.phtml
作为 an example, to override view.phtml
with your own template, you first have to create a new layout file. <Vendor>_<Module>/view/frontend/layout/wishlist_index_index.xml.
目前有两种覆盖块参数的方法。
wishlist_index_index.xml.
1 2 3 4 5 6 7 8 9 10 |
<?XML. 版本="1.0"?> <page XMLNS.:XSI.="http://www.w3.org/2001/XMLSchema-instance" XSI.:非普遍存在地沉思地区=“urn:magento:框架:查看/布局/ etc / page_configuration.xsd”> <body> <referenceBlock 姓名=“customer.wishlist”> <arguments> <argument 姓名=“模板” XSI.:类型=“细绳”>小贩_Module. :: View.phtml.</argument> </arguments> </referenceBlock> </body> </page> |
wishlist_index_index.xml.
1 2 3 4 5 6 7 8 9 10 |
<?XML. 版本="1.0"?> <page XMLNS.:XSI.="http://www.w3.org/2001/XMLSchema-instance" XSI.:非普遍存在地沉思地区=“urn:magento:框架:查看/布局/ etc / page_configuration.xsd”> <body> <referenceBlock 姓名=“customer.wishlist”> <action 方法=“沉淀物”> <argument 姓名=“模板” XSI.:类型=“细绳”>小贩_Module. :: View.phtml.</argument> </action> </referenceBlock> </body> </page> |
devdocs说,新方法是用布局XML覆盖模板的适当方法,但根据 问题#3356. 在Magento 2 Github Repo上,有许多新方法赢得的案例’工作。在这些情况下,可以使用旧的弃用方法直到问题已解决。
现在,您必须在布局文件中指定的位置放置新的自定义模板。对于这个例子,即 <Vendor>_<Module>/view/frontend/templates/view.phtml
模块中模板的路径无关紧要,只要它与您在模板属性中设置的路径匹配。我喜欢将模板放在与模块开始的原始模块中找到它的相同路径中’s模板目录,但为模板的模块名称添加一个目录’re overriding. For example, in your module, you would put a wishlist template in <Vendor>_<Module>/view/frontend/templates/wishlist/view.phtml
or for a catalog template it would be <Vendor>_<Module>/view/frontend/template/catalog/view.phtml
.
覆盖有一个额外的步骤生效。您必须为包含您正在修改的布局文件的模块添加序列。xml文件。对于此示例,您的etc / module.xml文件将如下所示。
模块.xml.
1 2 3 4 5 6 7 8 |
<?XML. 版本="1.0"?> <config XMLNS.:XSI.="http://www.w3.org/2001/XMLSchema-instance" XSI.:非普遍存在地沉思地区=“urn:magento:框架:module / etc / module.xsd”> <module 姓名=“vendor_module” setup_version.=“100.0.0”> <sequence> <module 姓名=“magento_wishlist”/> </sequence> </module> </config> |
This will ensure that the 玛托托_Wishlist
模块 will be loaded and added to the merged layout file before your module. This is necessary as it ensures your module’在引用的布局XML后,将解析S布局覆盖。否则,您的布局可以参考某些内容’T存在,因此您的布局覆盖将不适用。
你 may have found that there are some block definitions that contain a template attribute but do not contain a name attribute. This means you can’t覆盖从布局XML中覆盖块,就像通常在模块中一样。如果是块’s template attribute does not contain the 小贩_Module.
prefix you can utilize the class preference method to override the template.
In this example, we will be overriding the block containing the cart/item/default.phtml
模板 in found in 玛托托/Checkout/view/frontend/layout/checkout_cart_item_renderers.xml
.
1 |
<block 班级=“Magento \ checkout \ block \ cart \ Item \渲染器” 作为=“虚拟的” 模板=“购物车/项目/ default.phtml”> |
The class attribute on the block sets the scope for the template path so a 小贩_Module.
prefix is unnecessary if the template is in the same module as the block’班级。这意味着所有需要更改模板’S模块范围是更改块’S类在您的di.xml文件中具有类首选项。
di.xml.
1 2 3 4 |
<?XML. 版本="1.0"?> <config XMLNS.:XSI.="http://www.w3.org/2001/XMLSchema-instance" XSI.:非普遍存在地沉思地区=“urn:magento:框架:objectManager / etc / config.xsd”> <preference 为了=“Magento \ checkout \ block \ cart \ Item \渲染器” 类型=“供应商\ module \ block \ checkout \ cart \ Item \渲染器” /> </config> |
现在你必须确保即使你没有’实际上需要做任何事情。为此,您只需创建骨架块。
renderer.php.
1 2 3 4 5 6 7 8 |
<?php / ** *此块用作骨架类以更改块定义的范围。 *块上的模板属性现在将默认为此模块而不是 *原始块定义上的核心模块。 */ 命名空间 小贩\模块\堵塞\退房\大车\物品; 班级 渲染器 延伸 \玛托托\退房\堵塞\大车\物品\渲染器 {} |
要完成模板覆盖,您只需要添加您的模板,如果您正在执行从布局覆盖普通模板,则会添加您的模板。在这种情况下,该路径将是 小贩/Module/view/frontend/templates/cart/item/default.phtml
此时,这应该是显而易见的,这是多大的破解。它只是在极少数案例中谨慎。如果您认为您可能有这样的案例,请考虑是否有其他替代方案,我将在本文后面列出。考虑可能想要做类似您正在做的事情的其他模块的后果。希望,这个问题最终将是固定的,这种黑客将不再需要。
The class preference is an acceptable option when you are wanting to override the template for all instances of a class and the 小贩_Namespace
prefix is missing from the template attribute on block definition. However, there may be times when you need to be more targeted. The class may be used for multiple templates or the 小贩_Module.
prefix might be set. In these cases, a plugin is the best option. For this example we will override 玛托托_Catalog::category/products.phtml
with our own template using a plugin. I won’如果你逃离,那么在插件上会很详细’已经熟悉他们,请阅读 玛托托 2 devdoc在插件上 在继续之前。
类别视图模板的原始块定义如下所示
1 |
<block 班级=“Magento \目录\块\类别\ View” 姓名=“类别。产品” 模板=“magento_catalog :: category / products.phtml”> |
So our plugin will need to hook into the class 玛托托\Catalog\Block\Category\View
. The toHtml()
method, inherited by 玛托托\Framework\View\Element\Template
, retrieves the template and turns it into html. To override the template that gets retrieved by that method, the $_template
variable needs to be changed to your own template. Fortunately, the Template class already has a method to do that. With this understanding, we can create our plugin and di.xml files.
di.xml.
1 2 3 4 5 6 |
<?XML. 版本="1.0"?> <config XMLNS.:XSI.="http://www.w3.org/2001/XMLSchema-instance" XSI.:非普遍存在地沉思地区=“urn:magento:框架:objectManager / etc / config.xsd”> <type 姓名=“Magento \目录\块\类别\ View”> <plugin 姓名=“module_catalog_category_view_override_template” 类型=“vendor \ module \ plugin \ catalog \ block \ category \ View” /> </type> </config> |
view.php.
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php 命名空间 小贩\模块\插入\目录\堵塞\类别; 班级 看法 { 民众 功能 BeforeTohtml.(\玛托托\目录\堵塞\类别\看法 $主题) { 如果 ($模板 ===. 'magento_catalog :: category / products.phtml') { $主题->沉淀件('小贩_>模块::目录/类别/ products.phtml'); } } } |
The plugin could be set on a few other methods but I chose toHtml because it is the method in which the template is first used. This method of overriding a template is not recommended except when necessary. It should only be used if the block does not have a name, has a 小贩_Module.
prefix and/or has a class that handles multiple templates. To complete the template override just place your template in your module in the appropriate location,<Vendor>/<Module>/view/frontend/templates/catalog/category/products.phtml
没有一种特定的方法应该在所有场景中使用。如果您正在构建主题,请使用模板路径方法。如果要构建模块,请使用布局方法。对于开发人员试图弄清楚核心Magento模板已经被覆盖的地方,这些是他们所看到的两个地方。如果您正在构建模块,并且您遇到无法按名称引用的块,则可以使用两个非传统方法之一来覆盖该块’s template.
要在页面上修改某些内容,覆盖模板并不总是最好的选择。另一个模块可以在四种方法中的任何一种中覆盖覆盖,块上的名称可以随更新改变,或者分配给块的类可能会改变。当然在许多情况下,它是最好的,如果不是唯一的选择。但是,有些人会更好地走另一个路线。
Many times, the only change required to a template is an addition to the beginning or end of that template. In these cases, if the block defining the template you want to override is nested inside a container, you can simply create your own block and place it before or after the block you previously wanted to override. One of the distinguishing characteristics between blocks and containers is that children of blocks must be explicitly called in order to be rendered while children of containers will render all of their children blocks and containers. So all that is required to add your new markup to the wishlist page is to create your own layout/wishlist_index_index.xml.
file, like this:
1 2 3 4 5 6 7 8 |
<?XML. 版本="1.0"?> <page XMLNS.:XSI.="http://www.w3.org/2001/XMLSchema-instance" XSI.:非普遍存在地沉思地区=“urn:magento:框架:查看/布局/ etc / page_configuration.xsd”> <body> <referenceContainer 姓名=“内容”> <block 班级=“Magento \ Framework \ View \ Element \模板” 姓名=“有些.block” 模板=“Vendor_Module :: some-template.phtml” 后=“customer.wishlist”/> </referenceContainer> </body> </page> |
这是一个’T推荐但对于您真正想要避免覆盖模板删除元素的情况,您可以使用JS或CSS删除元素。它’很容易认为这是在易于实现方面的好主意,但它通常不是最好的解决方案。如果过于频繁,您可以拥有大块的HTML,但是aren’t显示给用户。这可以增加页面加载时间并导致凌乱,难以维护HTML和CSS。什么都没有明确的线条“too frequent”因此,除非绝对必要,否则最好避免这种选择。
在Magento 2中覆盖JS ’T始终需要覆盖它初始化的模板。您可以覆盖jQuery UI小部件上的函数和对象,就像您将在您延伸的PHP类上覆盖变量或方法。要执行此操作,请先在主题或模块中创建JS文件:
<Vendor>/<Theme>/web/js/customAccordion.js
<Vendor>/<Module>/view/frontend/web/js/customAccordion.js
自定义.js.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
定义([ 'jquery', 'jquery / ui', '法师/手风琴' ], 功能($){ $.小部件('小贩_Module.customAccordion', $.法师.手风琴, { _创造: 功能() { //自定义代码 } }); 返回 $.小贩_Module..自定义; }); |
现在为您的CustomAccordion小部件创建映射:
<Vendor>/<Theme>/requirejs-config.js
<Vendor>/<Module>/view/frontend/requirejs-config.js
Requirejs-config.js.
1 2 3 4 5 6 7 |
var. 配置 = { 地图: { '*': { '手风琴': '小贩_Module/js/customAccordion' } } }; |
现在,随时随地包括或初始化手风琴,您的自定义手风琴将被加载。了解更多信息。查看此Magento 2 DevDoc: 自定义默认的Magento jQuery小部件
玛托托 2具有非常简单的方法覆盖文本的方法。您可以通过将翻译添加到主题或模块中与要更改的文本行的模块添加到它们来执行此操作,并使用您设置的任何字符串替换它。这种方法也是如此’t被认为是最好的做法,但有时候值得折衷,而不是必须覆盖大模板来制作简单的文本改变。要了解更多信息,请阅读Magento 2 DevDocs上的本指南: 使用翻译词典自定义字符串。在使用此方法时,您需要小心’重新翻译用于多个位置。
你’ve学到了好的,坏的,丑陋的magento 2模板覆盖。覆盖模板的两种主要方法是“good”,但并非总是必要的。他们俩“bad”覆盖模板的方法几乎从未有必要,甚至应该被认为是一种需要在可能的时候更换的黑客。模板覆盖是一种快速且简单的方法,可以在Magento 2中进行更改,它们可以很容易地滥用。当您有选择时,请考虑覆盖模板的替代方案。
9 Comments
你好,
我是magneto2的新手。我希望禁用Magento2模板中的响应视图。我能怎么做…
它是什么“responsive view”?
漂亮的教程。这将适用/兼容magento 2.1.x吗?
谢谢
嗨Nathan,
感谢您分享本文,我正在寻找主题文件路径和布局XML文件的帮助,用于将自定义信息添加到Magento模块,您的文章帮助了我在添加主题漏洞路径中也可以为核心布局添加我找到这篇文章, //www.cloudways.com/blog/customize-magento-modules-through-layout-xml-files/ ,希望这将有助于每个人并继续发布更多我会跟进。
你好,
感谢分享。这里 ’我发现的另一个指南,它也是一个有用的指南: //magenticians.com/magento-2-override-block/
I’D阅读关于为magento 2创建自定义主题的十几个教程。但这是第一个以全面的方式解释它的教程。– Thanks!
你好,
感谢您分享这个令人敬畏的教程。在我的研究中,我发现了另一个关于Magneto 2布局,模板,块的伟大指南。这里是: //magenticians.com/using-magento-2-blocks-layouts-templates/
希望它能帮助您的读者更多ðÿ™,
感谢分享!
令人敬畏的教程….thanks a ton!!!