如何在v2.1中覆盖块


14

我正在尝试覆盖Magento 2.1中的Topmenu块,但找不到任何指导。我在这里和其他地方找到的所有内容似乎仅适用于2.0版,该版本似乎使用了不同的文件夹结构,或者仅包含部分代码示例,希望我已经知道它们的适当上下文(我不知道)。

我当前的自定义主题文件夹结构为app/design/frontend/Vendor/theme_name。在其中,我有注册,主题和作曲家文件以及各个模块(例如Magento_Theme和)的文件夹Magento_Search

据我了解,我需要etc/di.xml从如下文件开始,从这里编辑:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
  <preference for="Magento\Theme\Block\Html\Topmenu" type="[Namespace]\[Module]\Block\Html\Topmenu" />
</config>

我也了解下一步是添加一个Block/Html/Topmenu.php类似下面的文件(同样从上面的源代码编辑):

namespace [Namespace]\[Module]\Block\Html;

class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{

  protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
  {

  }

}

但是,我不清楚我应该用于[Namespace]和以及[Module]将这些文件放在何处。我尝试使用供应商和主题名称,并将etcBlock文件夹放在中app/design/frontend/Vendor/theme_name,以及将它们放在中app/design/frontend/Vendor/theme_name/Magento_Theme,将名称空间修改为Vendor\theme_name\Magento_Theme\Block\Html,但都没有任何效果。

如果有人可以帮助您确切地解释在2.1版中重写Topmenu块(以及通过推断任何其他块)需要做的事情,我将不胜感激。

附录

我尝试了Khoa TruongDinh的回答,但没有任何效果。我使用了以下文件:

app/code/Vendor/MagentoTheme/Block/Html/Topmenu.php

<?php

namespace Vendor\MagentoTheme\Block\Html;

class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{

  protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
  {

    $html = '';

    if (!$child->hasChildren())
    {
      return $html;
    }

    $colStops = null;

    if ($childLevel == 0 && $limit)
    {
      $colStops = $this->_columnBrake($child->getChildren(), $limit);
    }

    // Added "test" class to test
    $html .= '<ul class="level' . $childLevel . ' test submenu">';
    $html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops);
    $html .= '</ul>';

    return $html;

  }

}

app/code/Vendor/MagentoTheme/composer.json

{
    "name": "vendor/magento-theme",
    "description": "",
    "require": {
        "php": "~5.5.0|~5.6.0|~7.0.0",
        "magento/framework": "100.0.*"
    },
    "type": "magento2-module",
    "version": "100.0.1",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "autoload": {
        "files": [ "registration.php" ],
        "psr-4": {
            "Vendor\\MagentoTheme\\": ""
        }
    }
}

app/code/Vendor/MagentoTheme/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
  <preference for="Magento\Theme\Block\Html\Topmenu" type="Vendor\MagentoTheme\Block\Html\Topmenu" />
</config>

app/code/Vendor/MagentoTheme/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_MagentoTheme" setup_version="1.0.0"></module>
</config>

app/code/Vendor/MagentoTheme/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
  \Magento\Framework\Component\ComponentRegistrar::MODULE,
  'Vendor_MagentoTheme',
  __DIR__
);

然后,我已经删除的内容pub/static/frontendvar/generation以及var/view_preprocessed和冲洗Magento的缓存。子菜单没有添加预期的“测试”类:

<ul class="level0 submenu ui-menu ui-widget ui-widget-content ui-corner-all" role="menu" aria-expanded="false" style="display: none; top: 52.6719px; left: 487.5px;" aria-hidden="true">...</ul>

您尝试创建多个子类别?
Khoa TruongDinh'9

我不确定你是什么意思。目前,我只是想在子菜单中添加“测试”类,ul以确认我已成功覆盖Topmenu类。
MichaelRushton '16

您该怎么做?我的向导可以帮助您吗?
Khoa TruongDinh'9

据我所知,我按照您的指示进行了操作,但是没有用。我的自定义Topmenu模块将被忽略,并且正在使用默认行为。
MichaelRushton '16

在周末,我将再次检查并提供您解决方案。
Khoa TruongDinh'9

Answers:


20

覆盖块:

app/code文件夹下创建自己的模块。
我们可以preference用来覆盖Magento 2中的类。

应用程序/代码/供应商/模块/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
  <preference for="Magento\Theme\Block\Html\Topmenu" type="Vendor\Module\Block\Html\Topmenu" />
</config>

应用程序/代码/供应商/模块/块/HTML/Topmenu.php

<?php

namespace Vendor\Module\Block\Html;

class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{

    protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
    {

    }

}

临时解决方案:
当前,似乎上述步骤无法完全覆盖该块。我们需要创建新的自定义主题。然后,创建default.xml文件:

应用/设计/前端/供应商/主题/ Magento_Theme /布局/default.xml

<?xml version="1.0"?>

<page layout="3columns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="default_head_blocks"/>
    <referenceBlock name="catalog.topnav" class="Vendor\Module\Block\Html\Topmenu" template="Magento_Theme::html/topmenu.phtml"/>
</page>

这可能是Magento的错误:改写块时我们是否被迫在Magento2中重写模板?

[编辑]

1)我们可以设置模板:

应用程序/代码/供应商/模块/块/HTML/Topmenu.php

public function setTemplate($template)
{
    return parent::setTemplate('Vendor_Module::custom-menu.phtml');
}

2)通过Xml设置模板:

例如:

应用/代码/供应商/模块/视图/前端/布局/checkout_cart_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.cart">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">Magento_Checkout::cart.phtml</argument>
            </action>
        </referenceBlock>
    </body>
</page>

记住创建registration.phpmodule.xml

我们创建新模块是因为我们要重写Magento的类。当我们想覆盖任何类时,我们必须创建新的module

下的自定义主题app/design/frontend包含:--
layout
--templates
--js
--html模板(Knockout模板)-- less
,css
--etc ...

在这里这里阅读更多。

自动加载标准和命名约定:

对于[Namespace][Module],我们应该在此处阅读更多内容:

http://www.php-fig.org/psr/psr-0/
http://www.php-fig.org/psr/psr-4/
http://alanstorm.com/magento_2_autoloader_and_class_generation


谢谢,但是我无法使它正常工作。我已将我的尝试编辑为我的问题,以便您可以看到我不可避免地出了错。
MichaelRushton '16

什么是模板?
MichaelRushton '16

我更新了答案。似乎有一个Magento错误。我们需要创建新的自定义主题。然后,创建布局以再次设置类。
Khoa TruongDinh'9

是的,那行得通。非常感谢你。浪费了一天的时间...
MichaelRushton '16

我必须覆盖位于我的自定义theme.xml文件中的custom_account_create.xml中的块文件。该文件位于Magento_Customer文件夹中。哪个default.xml我必须更改magento_theme或magento_customer?我无法覆盖block.i正在使用Magento2.1,最好移动Magento 2.1.3?
vijay b'2

3

用于覆盖目录产品ListProduct块。

1)在文件夹中创建di.xml文件Vendor/Module/etc

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Model\Product" type="Vendor\Module\Model\Rewrite\Catalog\Product" />
</config>

2)在文件夹中创建ListProduct.php阻止文件Vendor/Module/Block/Rewrite/Product

<?php
namespace Vendor\Module\Block\Rewrite\Product;

class ListProduct extends \Magento\Catalog\Block\Product\ListProduct
{
    public function _getProductCollection()
    {
        // Do your code here
    }
}

用于替代目录产品型号。

1)之前在di.xml中添加首选项

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Model\Product" type="Vendor\Module\Model\Rewrite\Catalog\Product" />
</config> 

2)在文件夹中创建Product.php模型文件Vendor/Module/Model/Rewrite/Catalog

<?php
namespace Vendor\Module\Model\Rewrite\Catalog;

class Product extends \Magento\Catalog\Model\Product
{
    public function isSalable()
    {
        // Do your code here

        return parent::isSalable();
    }

}

对于覆盖控制器

1)di.xml中添加首选项

2)在以下位置创建View.php控制器文件Vendor/Module/Controller/Rewrite/Product

class View extends \Magento\Catalog\Controller\Product\View
{
    public function execute()
    {
        // Do your stuff here
        return parent::execute();
    }
}

您可以使用相同的方法覆盖其他块,模型和控制器。


似乎重写类\ Magento \ Catalog \ Block \ Product \ ListProduct不起作用(在Magento 2.2中也许吗?),请参考链接-github.com/magento/magento2/issues/13152
Aniruddha A Deshpande


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.