Comment remplacer des blocs dans v2.1

14

J'essaie de remplacer le bloc Topmenu dans Magento 2.1 mais je ne trouve aucun guide pour le faire. Tout ce que j'ai trouvé ici et ailleurs semble ne s'appliquer qu'à la version 2.0 qui semble utiliser une structure de dossiers différente ou n'a que des exemples de code partiel qui m'attendent à connaître déjà leur contexte approprié (ce que je ne sais pas).

Ma structure de dossiers actuelle pour un thème personnalisé est app/design/frontend/Vendor/theme_name. Dans ce document, j'ai les fichiers d'enregistrement, de thème et de compositeur ainsi que des dossiers pour les différents modules, par exemple Magento_Themeet Magento_Search.

D'après ce que je comprends, je dois commencer avec un etc/di.xmlfichier comme ci-dessous, édité à partir d' ici :

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

Je comprends également que l'étape suivante consiste à ajouter un Block/Html/Topmenu.phpfichier comme celui ci-dessous (à nouveau modifié à partir de la source ci-dessus):

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

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

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

  }

}

Cependant, il n'est pas clair pour moi à quoi je dois utiliser [Namespace]et [Module], ou où placer ces fichiers. J'ai essayé d'utiliser le nom du fournisseur et du thème, et de placer les dossiers etcet , ainsi que de les placer, en modifiant les espaces de noms , mais aucun n'a d'effet.Blockapp/design/frontend/Vendor/theme_nameapp/design/frontend/Vendor/theme_name/Magento_ThemeVendor\theme_name\Magento_Theme\Block\Html

Si quelqu'un pouvait aider à expliquer exactement ce que je dois faire pour remplacer le bloc Topmenu (et par déduction tout autre bloc) dans la version 2.1, je serais très apprécié.

Addenda

J'ai essayé la réponse de Khoa TruongDinh mais cela n'a eu aucun effet. J'ai utilisé les fichiers suivants:

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

Je l' ai ensuite retiré le contenu pub/static/frontend, var/generationet var/view_preprocessed, et rincée le cache Magento. Le sous-menu n'a pas la classe "test" prévue ajoutée:

<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
la source
Vous avez essayé de créer plusieurs sous-catégories?
Khoa TruongDinh
Je ne sais pas ce que tu veux dire. Pour le moment, j'essaie simplement d'ajouter une classe "test" au sous-menu ulpour confirmer que j'ai réussi à remplacer la classe Topmenu.
MichaelRushton
Comment pouvez-vous faire cela? Mon guide peut vous aider?
Khoa TruongDinh
J'ai suivi vos instructions du mieux que j'ai compris, mais cela n'a pas fonctionné. Mon module Topmenu personnalisé est ignoré et le comportement par défaut est utilisé.
MichaelRushton
Le week-end, je vais vérifier à nouveau et vous donner ma solution.
Khoa TruongDinh

Réponses:

20

Remplacer le bloc:

Créez votre propre module sous app/codedossier.
Nous pouvons utiliser preferencepour remplacer la classe dans 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)
    {

    }

}

Solution temporaire:
actuellement, il semble que les étapes ci-dessus ne peuvent pas remplacer complètement le bloc. Nous devons créer un nouveau thème personnalisé. Et puis, créez le default.xmlfichier:

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>

Il s'agit peut-être d'un bogue de Magento: sommes-nous obligés de réécrire un modèle dans Magento2 lors de la réécriture d'un bloc?

[ÉDITER]

1) Nous pouvons définir le modèle:

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

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

2) Définissez le modèle via Xml:

Par exemple:

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>

N'oubliez pas de créer registration.phpet module.xml.

Nous créons le nouveau module parce que nous remplaçons la classe de Magento. Lorsque nous voulons remplacer une classe, nous devons créer un nouveau module .

Le thème personnalisé sous app/design/frontendcontient:
--layout
--templates
--js
--html templates (Knockout templates)
--less, css
--etc ...

En savoir plus ici et ici .

Norme de chargement automatique et convention de dénomination:

Pour [Namespace]et [Module], nous devrions en savoir plus ici:

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
la source
Merci, mais je n'ai pas réussi à faire fonctionner cela. J'ai modifié ma tentative dans ma question afin que vous puissiez voir où je me suis inévitablement trompé.
MichaelRushton
Quel est le modèle?
MichaelRushton
J'ai mis à jour ma réponse. Semble qu'il y a un bogue Magento. Nous devons créer un nouveau thème personnalisé. Et puis, créez la disposition pour définir à nouveau la classe.
Khoa TruongDinh
Oui, ça a marché. Merci beaucoup. Une journée perdue sur un bug ...
MichaelRushton
je dois remplacer le fichier de blocage dans custom_account_create.xml situé dans mon fichier theme.xml personnalisé est dans le dossier Magento_Customer.which default.xml je dois changer magento_theme ou magento_customer ?? je ne peux pas remplacer block.i j'utilise Magento2.1 est -il préférable de déplacer Magento 2.1.3 ??
vijay b
3

Pour remplacer le produit ListProduct du catalogue.

1) Créez un fichier di.xml dans le dossierVendor/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) Créer un fichier bloc ListProduct.php dans un dossierVendor/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
    }
}

Pour remplacer le modèle de produit du catalogue.

1) Ajoutez une préférence dans di.xml avant

<?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) Créer un fichier modèle Product.php dans un dossierVendor/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();
    }

}

Pour remplacer le contrôleur

1) Ajouter une préférence en di.xml

2) Créez le fichier du contrôleur 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();
    }
}

Vous pouvez remplacer d'autres blocs, modèles et contrôleurs en utilisant cette même approche.

Prince Patel
la source
On dirait que le remplacement de la classe \ Magento \ Catalog \ Block \ Product \ ListProduct ne fonctionne pas (dans Magento 2.2 Peut-être?), Reportez-vous au lien - github.com/magento/magento2/issues/13152
Aniruddha A Deshpande
0

Pour remplacer la classe, vous devez créer un module où vous pouvez ajouter le fichier etc/di.xmlet Block/Html/Topmenu.php(ci-dessus le code que vous avez publié)

Namespace est le nom de votre fournisseur et Module est le nom de votre module. Par exemple: Magento est l'espace de noms et le thème est le nom du module.

Pour plus d'informations sur la création d'un module, http://devdocs.magento.com/guides/v2.1/extension-dev-guide/build/module-file-structure.html#module-file-structure

Mike
la source
0

À cause de ce bogue: https://github.com/magento/magento2/issues/3724, vous ne pouvez pas simplement préférer les classes de blocs.

1) (De préférence) Ce qui fonctionne à la place est d'utiliser un plugin pour cette classe et de changer ce dont vous avez besoin. http://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html

2) Ou si vous voulez vraiment faire la préférence, vous devez également copier le modèle du noyau vers votre module / thème et mettre à jour avec xml afin qu'il utilise ce modèle à la place, alors cela commencera comme par magie.

OZZIE
la source