如何在Magento 1中覆盖/重写块类?


12

注意:这是一个规范问题,旨在全面说明块重写的工作方式,并且可以用作更具体的“如何覆盖块X”或“为什么我的重写不起作用”问题的重复目标。

另请参阅:寻找有关Magento 1替代的规范问题

假设我必须在自定义模块中更改核心块类(更改方法或添加方法)。我该如何逐步进行?

Answers:


23

每个块或块组都在这样config.xml的模块文件中声明(在<global>标记内)。
这是目录模块中的示例

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

这意味着,一个块可以使用别名被实例化catalog/class_name_here,其中class_name_here是从前缀起始类路径的其余部分。
这意味着catalog/class_name_here默认情况下将映射到Mage_Catalog_Block_Class_Name_Here

要重写一个块,您需要创建一个模块,该模块取决于您Magento_Catalog在示例中尝试更改的模块()。
并且您需要config.xml<global>标记下将其添加。

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

然后创建类YourNamespace_YourModule_Block_Your_New_Class_Here(遵循ZF文件夹结构)并使该类扩展原始类。

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

完成后,禁用编译并再次启用它(如果需要)并清除缓存。

这不适用于抽象块。
它仅适用于实例化的类。

假设您要重写文件app \ code \ core \ Mage \ Catalog \ Block \ Product \ View \ Options \ Type \ Select.php,该文件Mage_Catalog_Block_Product_View_Options_Type_Select在您自己的模块Marius_Test中具有该类。

然后,您将需要在此条目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
}

不起作用。我试图覆盖类Mage_Catalog_Block_Product_View_Options_Type_Select应用程序\代码\本地\ WR \ EPO \块\目录\块\产品\查看\选项\型号\ Select.php。我是这样尝试的:codepen.io/anon/pen/WYOqBr
黑色

如果不起作用,您认为我的回答是错误的,因此您对它不满意,而不是认为您做错了什么。无论如何...将其替换<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><product_view_options_type_select>WR_EPO_Block_Catalog_Block_Product_View_Options_Type_Select</product_view_options_type_select>并确保内部没有空间product_view_options_type_select
Marius

我之所以投票,是因为您的回答不准确,即使我一步一步地遵循,也没有得出正确的结果。您写道我们必须使用类名,所以我使用了它,但是它没有用。我们必须使用product_view_options_type_select而不是真实的类名Mage_Catalog_Block_Product_View_Options_Type_Select。如果您相应地更改答案,那么我会投票赞成。
黑色

如果您逐步阅读它,则会错过一步。我在这里解释什么是类别名。如果您只是复制粘贴替换,则可以正常使用。17个人了解。我认为我的解释正确
马吕斯

是的,但是缺少一个很好的例子,因此我们可以确保我们正确地理解了您的理论
Black,

4

对于我的观点,重写和重写这两个是不同的东西,

覆写:

当我们使用设计后备机制时,我们正在做覆盖

改写:

当我们在类中重写magento Core类时,我们正在进行重写。

1)替代示例:

如果我需要覆盖app/code/core/Mage/Catalog/Block/Product/List.php文件,则使用以下所示的相同路径复制到本地模块中app/code/local/Mage/Catalog/Block/Product/List.php

magento不建议这样做,但是您可以这样做。

2)重写示例:

如果我想重写此块类,Mage_Adminhtml_Block_Sales_Order_Create则可以在模块config.xml中进行编码,如下所示

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

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

在我班上 Trimantra_Smallchanges_Block_Adminhtml_Sales_Order_Create

我编码如下

class Trimantra_Smallchanges_Block_Adminhtml_Sales_Order_Create extends Mage_Adminhtml_Block_Sales_Order_Create {
      My Function Or funcions That I want to Rewrite..
}

2

在此添加的重要一点是,块重写(以及Magento模块的所有其他重写)意味着更高的维护工作量,因此,应将其视为在配置操作,事件和主题自定义之后扩展功能的最后机会。

潜在问题1:当您或其他维护人员更新Magento的源文件时,重写的模板将不会更新。意味着安全修复或改进不会应用到您的代码中。这同样适用于其他重写的类,包括Block,但是取决于完成了多少重写(请参见下文)。

潜在的问题2:重写的块(或其他类)可能似乎是由您或另一个维护人员将尝试安装的另一个扩展所重写的。然后,您将必须解决此冲突。

备选方案1:使用事件,即浏览您将要重写的代码,并检查是否存在可用于实现所需功能的事件。

替代方案2:聪明地重写,即环顾四周:也许检查要重写的类被实例化的位置,并检查是否可以影响通过配置或事件选择哪个类;也许有一个类可以让您覆盖3行方法来替换类名,而不是将30行方法从原始类复制到重写的类。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.