Como substituir blocos na v2.1

14

Estou tentando substituir o bloco Topmenu no Magento 2.1, mas não consigo encontrar nenhum guia para fazer isso. Tudo o que encontrei aqui e em outros lugares parece se aplicar apenas à versão 2.0, que parece usar uma estrutura de pastas diferente ou possui apenas exemplos de códigos parciais que esperam que eu já conheça o contexto adequado (o que não sei).

Minha estrutura de pastas atual para um tema personalizado é app/design/frontend/Vendor/theme_name. Dentro disso, tenho os arquivos de registro, tema e compositor, além de pastas para os vários módulos, por exemplo, Magento_Themee Magento_Search.

Pelo que entendi, preciso começar com um etc/di.xmlarquivo como o abaixo, editado a partir daqui :

<?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>

Também entendo que o próximo passo é adicionar um Block/Html/Topmenu.phparquivo como o abaixo (novamente editado a partir da fonte acima):

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

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

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

  }

}

No entanto, não está claro para mim o que devo usar [Namespace]e [Module]nem onde colocar esses arquivos. Tentei usar o nome do fornecedor e do tema, colocar as pastas etce , além de colocá-las , alterar os espaços para nome , mas nenhum deles tem efeito.Blockapp/design/frontend/Vendor/theme_nameapp/design/frontend/Vendor/theme_name/Magento_ThemeVendor\theme_name\Magento_Theme\Block\Html

Se alguém puder ajudar a explicar exatamente o que preciso fazer para substituir o bloco Topmenu (e por inferência de qualquer outro bloco) na versão 2.1, eu ficaria muito agradecido.

Termo aditivo

Eu tentei a resposta de Khoa TruongDinh , mas ela não teve efeito. Eu usei os seguintes arquivos:

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__
);

Eu, em seguida, removido o conteúdo pub/static/frontend, var/generatione var/view_preprocessed, e corou o cache Magento. O submenu não possui a classe "teste" pretendida adicionada:

<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>
MichaelRushton
fonte
Você tentou criar várias subcategorias?
Khoa TruongDinh
Não sei bem o que você quer dizer. No momento, estou apenas tentando adicionar uma classe "test" ao submenu ulpara confirmar que substitui com êxito a classe Topmenu.
MichaelRushton #
Como você pode fazer isso? Meu guia pode ajudá-lo?
precisa saber é o seguinte
Eu segui suas instruções da melhor maneira que entendi, mas não funcionou. Meu módulo Topmenu personalizado é ignorado e o comportamento padrão está sendo usado.
MichaelRushton
No final de semana, vou verificar novamente e fornecer a minha solução.
precisa saber é o seguinte

Respostas:

20

Substituir bloco:

Crie seu próprio módulo na app/codepasta
Podemos preferencesubstituir a classe no Magento 2.

aplicativo / código / fornecedor / módulo / 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>

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

<?php

namespace Vendor\Module\Block\Html;

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

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

    }

}

Solução temporária:
atualmente, parece que as etapas acima não podem substituir completamente o bloco. Precisamos criar um novo tema personalizado. E então, crie o default.xmlarquivo:

app / design / front-end / fornecedor / tema / tema-magento / layout / 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>

Pode ser um bug do Magento: somos forçados a reescrever um modelo no Magento2 ao reescrever um bloco?

[EDITAR]

1) Podemos definir o modelo:

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

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

2) Defina o modelo via Xml:

Por exemplo:

app / code / Vendor / Module / view / frontend / layout / 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>

Lembre-se de criar registration.phpe module.xml.

Criamos o novo módulo porque estamos substituindo a classe Magento. Quando queremos substituir qualquer classe, precisamos criar um novo módulo .

O tema personalizado em app/design/frontendcontém:
--layout
--templates
--js
--html templates (modelos de Knockout)
--less, css -
etc ...

Leia mais aqui e aqui .

Padrão de carregamento automático e convenção de nomenclatura:

Para [Namespace]e [Module], devemos ler mais aqui:

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

Khoa TruongDinh
fonte
Obrigado, mas não consegui fazer isso funcionar. Editei minha tentativa na minha pergunta para que você possa ver onde eu inevitavelmente errei.
MichaelRushton #
Qual é o modelo?
MichaelRushton
Eu atualizei minha resposta. Parece que há um bug do Magento. Precisamos criar um novo tema personalizado. E então, crie o layout para definir a classe novamente.
precisa saber é o seguinte
Sim, isso funcionou. Muito obrigado. Um dia desperdiçado em um erro ...
MichaelRushton
Eu tenho que substituir o arquivo de bloco em custom_account_create.xml localizado no meu arquivo theme.xml personalizado está na pasta Magento_Customer.which default.xml eu tenho que mudar magento_theme ou magento_customer ?? melhor mover o Magento 2.1.3 ??
Vijay b
3

Para substituir o bloco ListProduct do produto do catálogo.

1) Crie um arquivo di.xml na pastaVendor/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) Crie o arquivo ListProduct.php Block na pastaVendor/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
    }
}

Para substituir o modelo de produto do catálogo.

1) Adicione preferência em di.xml antes

<?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) Crie o arquivo Product.php Model na pastaVendor/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();
    }

}

Para substituir o controlador

1) Adicione preferência em di.xml

2) Crie o arquivo View.php Controller emVendor/Module/Controller/Rewrite/Product

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

Você pode substituir outro bloco, modelo e controladores usando essa mesma abordagem.

Prince Patel
fonte
Looks como substituição de classe \ Magento \ Catalog \ Bloco \ Product \ ListProduct não funciona (? Em Magento 2.2 Talvez), consulte ligação - github.com/magento/magento2/issues/13152
Aniruddha A Deshpande
0

Devido a esse bug: https://github.com/magento/magento2/issues/3724, você não pode apenas preferir classes de bloco.

1) (Preferível) O que funciona é usar um plug - in para essa classe e alterar o que você precisa. http://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html

2) Ou se você realmente deseja fazer a preferência, também precisa copiar o modelo do núcleo para o seu módulo / tema e atualizar com xml, para que ele use esse modelo, então ele começará a funcionar magicamente.

OZZIE
fonte