Como sobrescrever / reescrever uma classe de bloco no Magento 1?

12

Nota: Essa é uma pergunta canônica que explica completamente como as reescritas de bloco funcionam e pode ser usada como destino duplicado para perguntas mais específicas "Como substituir o bloco X" ou "Por que minha reescrita não funciona"?

Veja também: Procurando perguntas canônicas sobre substituições do Magento 1

Digamos, eu tenho que fazer alterações em uma classe de bloco principal em um módulo personalizado (alterar métodos ou adicionar métodos). Como faço isso passo a passo?

Fabian Schmengler
fonte

Respostas:

23

Todo bloco ou grupo de blocos é declarado no config.xmlarquivo de um módulo como este (dentro da <global>tag).
Aqui está um exemplo do módulo de catálogo

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

Isso significa que um bloco pode ser instanciado usando o alias catalog/class_name_hereonde class_name_hereestá o restante do caminho da classe começando no prefixo.
Isso significa catalog/class_name_hereque será mapeado por padrão para Mage_Catalog_Block_Class_Name_Here.

Para reescrever um bloco, você precisa criar um módulo que dependa do módulo que você está tentando alterar ( Magento_Catalog) no meu exemplo.
E você precisa adicionar isso config.xmlabaixo da <global>tag.

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

Em seguida, crie a classe YourNamespace_YourModule_Block_Your_New_Class_Here(seguindo a estrutura de pastas do ZF) e faça com que essa classe estenda a classe original.

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

Quando terminar, desative a compilação e ative-a novamente (se necessário) e limpe o cache.

Isso não funcionará para blocos abstratos.
Funciona apenas para classes instanciadas.

Exemplo

Vamos supor que você queira reescrever o arquivo app \ code \ core \ Mage \ Catalog \ Block \ Product \ View \ Options \ Type \ Select.php que possui a classe Mage_Catalog_Block_Product_View_Options_Type_Selectem seu próprio módulo Marius_Test .

Então você precisaria desta entrada no seu 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
fonte
Não funciona. Tento sobrescrever a classe Mage_Catalog_Block_Product_View_Options_Type_Selectem app \ code \ local \ WR \ EPO \ Block \ Catalog \ Block \ Product \ View \ Options \ Type \ Select.php . Eu tentei assim: codepen.io/anon/pen/WYOqBr
Black
E se não der certo, você acha que minha resposta está errada e a diminuiu, em vez de pensar que talvez esteja fazendo algo errado. Enfim ... substitua-o <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>por <product_view_options_type_select>WR_EPO_Block_Catalog_Block_Product_View_Options_Type_Select</product_view_options_type_select>e verifique se não há espaços dentroproduct_view_options_type_select
Marius
Fiz uma votação negativa porque sua resposta não foi precisa e, embora eu a tenha seguido passo a passo, não produziu o resultado certo. Você escreveu que temos que usar o nome da classe, então eu o usei e não funcionou. Temos que usar em product_view_options_type_selectvez do nome da classe real Mage_Catalog_Block_Product_View_Options_Type_Select. Se você alterar sua resposta de acordo, eu votarei.
Preto
Se você leu passo a passo, você perdeu um passo. Aquele em que eu explico qual é o alias da classe. Se você copiar e colar, substitua-o. 17 pessoas entenderam. Eu acho que expliquei direito
Marius
Sim, mas um bom exemplo está faltando para que possamos assegurar que estávamos entendendo a sua teoria corretamente
preto
4

Para Meu ponto de vista, substitua e reescreva essas duas coisas diferentes,

Sobrepor:

Quando usamos o mecanismo de fallback de design, estamos substituindo

Reescrever:

Quando reescrevemos as magento Core classes em nossa classe, estamos reescrevendo.

1) Exemplo de substituição:

Se eu precisar substituir o app/code/core/Mage/Catalog/Block/Product/List.phparquivo, copio no meu módulo local com o mesmo caminho mostrado abaixoapp/code/local/Mage/Catalog/Block/Product/List.php

Isso não é sugerido pelo magento Mas você pode fazer dessa maneira.

2) Exemplo de reescrita:

Se eu quiser reescrever esta classe de bloco Mage_Adminhtml_Block_Sales_Order_Create, eu codifico no meu módulo config.xml

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

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

E na minha aula Trimantra_Smallchanges_Block_Adminhtml_Sales_Order_Create

Eu codigo como abaixo

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
fonte
2

É importante acrescentar aqui que as reescritas de bloco (assim como todas as outras reescritas dos módulos Magento) implicam em maior esforço de manutenção e, portanto, devem ser consideradas como uma última chance de estender a funcionalidade após manipulação de configuração, eventos e personalização de temas.

Problema potencial 1: O modelo reescrito não será atualizado quando você ou outro mantenedor atualizará os arquivos de origem do Magento. Significa que a correção ou melhoria de segurança não será aplicada ao seu código. O mesmo se aplica a outras classes reescritas, incluindo blocos, mas depende de quanto da reescrita foi feita (veja abaixo).

Problema potencial 2: o bloco reescrito (ou outra classe) pode parecer ser reescrito por outra extensão que você ou outro mantenedor tentará instalar. Então você terá que resolver esse conflito.

Alternativa 1: use eventos, ou seja, procure o código que você está prestes a reescrever e verifique se há eventos que possam ser usados ​​para obter a funcionalidade desejada.

Alternativa 2: Reescreva de forma inteligente, ou seja, olhe em volta: talvez verifique o local onde a classe que você vai reescrever é instanciada e verifique se você pode afetar qual classe é escolhida por meio de configurações ou eventos; talvez exista uma classe que permita substituir um método de 3 linhas para substituir o nome da classe em vez de copiar o método de 30 linhas da classe original para a reescrita.

Anton Boritskiy
fonte