Comment remplacer / réécrire une classe de bloc dans Magento 1?

12

Remarque: Il s'agit d'une question canonique qui explique en détail le fonctionnement des réécritures de blocs et peut être utilisée comme cible en double pour des questions plus spécifiques "Comment remplacer le bloc X" ou "Pourquoi ma réécriture ne fonctionne-t-elle pas".

Voir aussi: Recherche de questions canoniques sur les remplacements de Magento 1

Disons que je dois apporter des modifications à une classe de bloc de base dans un module personnalisé (modifier les méthodes ou ajouter des méthodes). Comment dois-je procéder, étape par étape?

Fabian Schmengler
la source

Réponses:

23

Chaque bloc ou groupe de blocs est déclaré dans le config.xmlfichier d'un module comme celui-ci (à l'intérieur de la <global>balise).
Voici un exemple du module catalogue

    <blocks><!-- marks definition of a block group -->
        <catalog><!-- unique alias for blocks in the module -->
            <class>Mage_Catalog_Block</class><!-- class prefix for all blocks -->
        </catalog>
    </blocks>

Cela signifie qu'un bloc peut être instancié en utilisant l'alias catalog/class_name_hereclass_name_hereest le reste du chemin de classe à partir du préfixe.
Cela signifie catalog/class_name_heresera mappé par défaut à Mage_Catalog_Block_Class_Name_Here.

Pour réécrire un bloc, vous devez créer un module qui dépend du module que vous essayez de changer ( Magento_Catalog) dans mon exemple.
Et vous devez l'ajouter dans la config.xmlsous la <global>balise.

<blocks>
    <catalog><!-- alias of the block group you are rewriting -->
        <rewrite><!-- reserved tag: specify that you are rewriting something -->
             <class_name_here>YourNamespace_YourModule_Block_Your_New_Class_Here</class_name_here> <!-- tag: the rest of the alias of the class you are rewriting. value: the name of your class that rewrites the core class -->
        </rewrite>
    </catalog>
</blocks>

Créez ensuite la classe YourNamespace_YourModule_Block_Your_New_Class_Here(en suivant la structure du dossier ZF) et faites étendre cette classe à la classe d'origine.

class YourNamespace_YourModule_Block_Your_New_Class_Here extends Mage_Catalog_Block_Class_Name_Here
{
    //your awesome code here
}

Lorsque vous avez terminé, désactivez la compilation et réactivez-la (si nécessaire) et videz le cache.

Cela ne fonctionnera pas pour les blocs abstraits.
Cela ne fonctionne que pour les classes instanciées.

Exemple

Supposons que vous souhaitiez réécrire le fichier app \ code \ core \ Mage \ Catalog \ Block \ Product \ View \ Options \ Type \ Select.php qui a la classe Mage_Catalog_Block_Product_View_Options_Type_Selectdans votre propre module Marius_Test .

Ensuite, vous auriez besoin de cette entrée dans votre config.xml:

<blocks>
    <catalog>
        <rewrite>
            <product_view_options_type_select>Marius_Test_Block_Catalog_Block_Product_View_Options_Type_Select</product_view_options_type_select>
        </rewrite>
    </catalog>
</blocks>

app \ code \ local \ Marius \ Test \ Block \ Catalog \ Product \ View \ Options \ Type \ Select.php :

class Marius_Test_Block_Catalog_Product_View_Options_Type_Select extends Mage_Catalog_Block_Product_View_Options_Type_Select
{
    //your awesome code here
}
Marius
la source
Ne marche pas. J'essaie d'écraser la classe Mage_Catalog_Block_Product_View_Options_Type_Selectdans app \ code \ local \ WR \ EPO \ Block \ Catalog \ Block \ Product \ View \ Options \ Type \ Select.php . Je l'ai essayé comme ceci: codepen.io/anon/pen/WYOqBr
Black
Et si cela ne fonctionne pas, vous pensez que ma réponse est fausse, alors vous votez contre au lieu de penser que vous faites peut-être quelque chose de mal. Quoi qu'il en soit ... remplacez-le <Mage_Catalog_Block_Product_View_Options_Type_Select> WR_EPO_Block_Catalog_Block_Product_View_Options_Type_Select </Mage_Catalog_Block_Product_View_Options_Type_Select>par <product_view_options_type_select>WR_EPO_Block_Catalog_Block_Product_View_Options_Type_Select</product_view_options_type_select>et assurez-vous qu'il n'y a pas d'espace à l'intérieurproduct_view_options_type_select
Marius
J'ai voté contre parce que votre réponse n'était pas précise et même si je l'ai suivie pas à pas n'a pas donné le bon résultat. Vous avez écrit que nous devons utiliser le nom de la classe, donc je l'ai utilisé et cela n'a pas fonctionné. Nous devons utiliser à la product_view_options_type_selectplace du vrai nom de classe Mage_Catalog_Block_Product_View_Options_Type_Select. Si vous modifiez votre réponse en conséquence, je voterai favorablement.
Black
Si vous le lisez étape par étape, vous avez manqué une étape. Celui où j'explique quel est l'alias de classe. Si vous copiez simplement le remplacement de la pâte, vous le faire fonctionner. 17 personnes ont compris. Je pense que je l'ai bien expliqué
Marius
Oui, mais il manque un bon exemple pour que nous puissions nous assurer que nous comprenions correctement votre théorie
Black
4

Pour mon point de vue, remplacer et réécrire ces deux choses sont différentes,

Passer outre:

Lorsque nous utilisons le mécanisme de secours de conception, nous effectuons un remplacement

Récrire:

Lorsque nous réécrivons les classes Magento Core dans notre classe, nous faisons de la réécriture.

1) Exemple de dérogation:

Si j'ai besoin de remplacer le app/code/core/Mage/Catalog/Block/Product/List.phpfichier, je copie dans mon module local avec le même chemin indiqué ci-dessousapp/code/local/Mage/Catalog/Block/Product/List.php

Ce n'est pas suggéré par magento Mais vous pouvez le faire de cette façon.

2) Exemple de réécriture:

Si je veux réécrire cette classe de bloc, Mage_Adminhtml_Block_Sales_Order_Createje code dans mon module config.xml comme ci-dessous

    <global>
        <blocks>
            <adminhtml>
                <rewrite>

                    <sales_order_create>Trimantra_Smallchanges_Block_Adminhtml_Sales_Order_Create</sales_order_create>
                </rewrite>
            </adminhtml>
        </blocks>
    </global>

Et dans ma classe Trimantra_Smallchanges_Block_Adminhtml_Sales_Order_Create

Je code comme ci-dessous

class Trimantra_Smallchanges_Block_Adminhtml_Sales_Order_Create extends Mage_Adminhtml_Block_Sales_Order_Create {
      My Function Or funcions That I want to Rewrite..
}
Murtuza Zabuawala
la source
2

Il est important d'ajouter ici que les réécritures de blocs (ainsi que toutes les autres réécritures des modules Magento) impliquent un effort de maintenance plus élevé et doivent donc être considérées comme une dernière chance d'étendre les fonctionnalités après la manipulation de la configuration, les événements et la personnalisation du thème.

Problème potentiel 1: le modèle réécrit ne sera pas mis à jour lorsque vous ou un autre responsable mettra à jour les fichiers source de Magento. Signifie que le correctif ou l'amélioration de sécurité ne sera pas appliqué à votre code. La même chose s'applique aux autres classes réécrites, y compris les blocs, mais dépend de la quantité de réécriture effectuée (voir ci-dessous).

Problème potentiel 2: le bloc réécrit (ou une autre classe) peut sembler être réécrit par une autre extension que vous ou un autre responsable tenterez d'installer. Ensuite, vous devrez résoudre ce conflit.

Alternative 1: utilisez des événements, c'est-à-dire fouillez dans le code que vous êtes sur le point de réécrire et vérifiez s'il existe des événements qui pourraient être utilisés pour obtenir la fonctionnalité souhaitée.

Alternative 2: Réécrivez intelligemment, c'est-à-dire regardez autour de vous: vérifiez peut-être l'endroit où la classe que vous allez réécrire est instanciée et vérifiez si vous pouvez affecter la classe choisie via la configuration ou les événements; il y a peut-être une classe autour qui vous permet de remplacer une méthode à 3 lignes pour remplacer le nom de classe au lieu de copier la méthode de 30 lignes de la classe d'origine à la réécrite.

Anton Boritskiy
la source