Cómo anular bloques en v2.1

14

Estoy tratando de anular el bloque Topmenu en Magento 2.1 pero no puedo encontrar ninguna guía para hacerlo. Todo lo que he encontrado aquí y en otros lugares parece aplicarse solo a la versión 2.0 que parece usar una estructura de carpetas diferente o solo tiene ejemplos de código parcial que espera que ya conozca su contexto adecuado (lo cual no sé).

Mi estructura de carpetas actual para un tema personalizado es app/design/frontend/Vendor/theme_name. Dentro de esto tengo los archivos de registro, tema y compositor, así como carpetas para los diversos módulos, por ejemplo, Magento_Themey Magento_Search.

Por lo que entiendo, necesito comenzar con un etc/di.xmlarchivo como el siguiente, editado desde aquí :

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

También entiendo que el siguiente paso es agregar un Block/Html/Topmenu.phparchivo como el siguiente (nuevamente editado de la fuente anterior):

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

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

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

  }

}

Sin embargo, no me queda claro para qué debo usar [Namespace]y [Module]dónde colocar estos archivos. Intenté usar el nombre del proveedor y el tema, y ​​colocar las carpetas etcy , así como colocarlas , modificando los espacios de nombres , pero ninguno tiene ningún efecto.Blockapp/design/frontend/Vendor/theme_nameapp/design/frontend/Vendor/theme_name/Magento_ThemeVendor\theme_name\Magento_Theme\Block\Html

Si alguien pudiera ayudarme a explicar exactamente lo que necesito hacer para anular el bloque Topmenu (y por inferencia cualquier otro bloque) en la versión 2.1, sería muy apreciado.

Apéndice

He intentado la respuesta de Khoa TruongDinh pero no ha tenido ningún efecto. He usado los siguientes archivos:

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

Entonces me he quitado el contenido de pub/static/frontend, var/generationy var/view_preprocessed, y tiraba el caché de Magento. El submenú no tiene la clase de "prueba" prevista agregada:

<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
fuente
¿Intentaste crear múltiples subcategorías?
Khoa TruongDinh
No estoy seguro de lo que quieres decir. En este momento solo estoy tratando de agregar una clase de "prueba" al submenú ulpara confirmar que he anulado con éxito la clase Topmenu.
MichaelRushton
¿Cómo puedes hacer esto? ¿Mi guía te puede ayudar?
Khoa TruongDinh
Seguí tus instrucciones lo mejor que entendí pero no funcionó. Mi módulo Topmenu personalizado se ignora y se está utilizando el comportamiento predeterminado.
MichaelRushton
El fin de semana, volveré a verificar y le daré mi solución.
Khoa TruongDinh

Respuestas:

20

Anular bloque:

Crea tu propio módulo en la app/codecarpeta.
Podemos usar preferencepara anular la clase en Magento 2.

app / code / Vendor / Module / 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)
    {

    }

}

Solución temporal:
actualmente, parece que los pasos anteriores no pueden anular el bloque por completo. Necesitamos crear un nuevo tema personalizado. Y luego, crea el default.xmlarchivo:

app / design / frontend / Vendor / Theme / Magento_Theme / 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>

Puede ser un error de Magento: ¿estamos obligados a reescribir una plantilla en Magento2 cuando reescribimos un bloque?

[EDITAR]

1) Podemos configurar la plantilla:

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

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

2) Establecer plantilla a través de Xml:

Por ejemplo:

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>

Recuerda crear registration.phpy module.xml.

Creamos el nuevo módulo porque estamos anulando la clase de Magento. Cuando queremos anular cualquier clase, tenemos que crear un nuevo módulo .

El tema personalizado debajo app/design/frontendcontiene:
--layout
--templates
--js
--html templates (Knockout templates)
--less, css
--etc ...

Lea más aquí y aquí .

Estándar de carga automática y convención de nombres:

Para [Namespace]y [Module], deberíamos leer más aquí:

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
fuente
Gracias, pero no pude hacer que esto funcione. He editado mi intento en mi pregunta para que pueda ver dónde inevitablemente me equivoqué.
MichaelRushton
¿Cuál es la plantilla?
MichaelRushton
Actualicé mi respuesta. Parece que hay un error de Magento. Necesitamos crear un nuevo tema personalizado. Y luego, cree el diseño para configurar la clase nuevamente.
Khoa TruongDinh
Sí, eso funcionó. Muchas gracias. Un día perdido en un error ...
MichaelRushton
tengo que anular el archivo de bloque en custom_account_create.xml ubicado en mi archivo theme.xml personalizado está en la carpeta Magento_Customer.which.xml ¿tengo que cambiar magento_theme o magento_customer? Es mejor mover Magento 2.1.3?
vijay b
3

Para anular el catálogo del producto ListProduct block.

1) Crear un archivo di.xml en la carpetaVendor/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) Crear el archivo de bloque ListProduct.php en la carpetaVendor/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 anular el modelo de catálogo del producto.

1) Agregue preferencia en 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) Crear archivo de modelo Product.php en la carpetaVendor/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 anular el controlador

1) Añadir preferencia en di.xml

2) Crear el archivo View.php Controller enVendor/Module/Controller/Rewrite/Product

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

Puede anular otros bloques, modelos y controladores utilizando este mismo enfoque.

Príncipe Patel
fuente
Parece anulación de la clase \ Magento \ Catálogo \ Bloque \ Producto \ ListaEl producto no funciona (en Magento 2.2 ¿Quizás?), Consulte el enlace - github.com/magento/magento2/issues/13152
Aniruddha A Deshpande
0

Para anular la clase, debe crear un módulo donde pueda agregar el archivo etc/di.xmly Block/Html/Topmenu.php(el código anterior publicado por usted)

donde Namespace es su nombre de proveedor y Module es su nombre de módulo. Por ejemplo: Magento es el espacio de nombres y el tema es el nombre del módulo.

Para obtener más información sobre cómo crear un módulo, http://devdocs.magento.com/guides/v2.1/extension-dev-guide/build/module-file-structure.html#module-file-structure

Miguel
fuente
0

Debido a este error: https://github.com/magento/magento2/issues/3724 no puedes simplemente preferir las clases de bloque.

1) (Preferible) Lo que funciona es utilizar un complemento para esa clase y cambiar lo que necesita. http://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html

2) O si realmente desea hacer la forma de preferencia, entonces también necesita copiar la plantilla desde el núcleo a su módulo / tema y actualizar con xml para que use esa plantilla, entonces mágicamente comenzará a funcionar ...

OZZIE
fuente