如何修改、扩展并重写Magento代码

作为一个开发者的你,肯定要修改Magento代码去适应你的业务需求,但是在很多时候我们不希望修改Magento的核心代码,这里有很多原因,
例如将来还希望升级Magento、还想使用更多的Magento代码。如果你正在寻找修改Magento代码的最佳方式,那么此篇文章将会是一个不错的教程。

适合对象:高级开发者

适合目标:开发者希望自定义修改Magento

当前版本:Magento versions: 1.4.0.1

作者:精东

重写Magento模块(Module)

第一步,你需要创建属于你自己代码的命名空间,例如MagentoNotes,App等,为了方便与大家分享代码,我将空间命名为App。

app/
     code/
            core/
            community/
            local/
                    App/

假如你现在打算修改Mage/Catalog/Block/Breadcrumbs.php这个文件,你可以在你的命名空间,App里添加一个新的模块 “Catalog”。接下来创建块(Block)目录,并复制Breadcrumbs.php到你的新目录中。这里还需要你创建一个config.xml
配置文件。

app/
     code/
            core/
            community/
            local/
                    App/
                               Catalog/
                                          Block/
                                                 Breadcrumbs.php
                                          etc/
                                                 config.xml

修改Breadcrumbs.php的类名为App_Catalog_Block_Breadcrumbs,并继承原类名Mage_Catalog_Block_Breadcrumbs。

现在,你需要激活你的新模块,这样magento才能够知道你的新模块。

创建文件app/etc/modules/App_All.xml,添加如下代码。

< ?xml version="1.0"?>
<config>
     <modules>
        <App_Catalog>
            <active>true</active>
            <codePool>local</codePool>
        </App_Catalog>
     </modules>
</config>

下面我们需要一个特殊的标签来复写掉Breadcrumbs,下面我们通过模块的配置文件来实现。

重写Magento区块(Blocks)

编辑文件“app/code/local/App/Catalog/etc/config.xml”

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <App_Catalog>
            <version>0.1.0</version>
        </App_Catalog>
    </modules>
    <global>
        <blocks>
            <catalog>
                <rewrite>
                        <breadcrumbs>App_Catalog_Block_Breadcrumbs</breadcrumbs>
                </rewrite>
            </catalog>
        </blocks>
    </global>
</config>

我们需要添加一个“blocks” 标签,或者在已经存在的“blocks”标签中添加内容。然后在模块名后面添加rewrite标签,在这个例子中模块名是“catalog”。然后我们看 “breadcrumbs”标签,这个标签帮助magento找到我们我们想修改的块。在我们的列子中,breadcrumbs是Magento核心代码
中的类名: app/code/core/Mage/Catalog/Block/Breadcrumbs.php。如果你有更多的目录层级,可以用下滑线来分隔。例如:

<blocks>
    <catalog>
        <rewrite>
                <category_view>App_Catalog_Block_Category_View</category_view>
        </rewrite>
    </catalog>
</blocks>

在这个例子中,我们重写了app/code/core/Mage/Catalog/Block/Category/View.php。

在breadcrumbs标签中的值是你的类名,这样Magento就可以获取你的类,因为类名与你的目录名一致。用过zend framework的人都知道,自动加载auto loader这个东西,它会跟你类名中的下滑线去你的目录中需要对应的类文件。记住一点,下滑线代表下一级别的文件夹,如果你的类名与你的文件目录名不一 致,那么Magento根本不会理睬你。

举例来说:


1

2

App_Catalog_Block_Breadcrumbs
→ /app/code/local/App/Catalog/Block/Breadcrumbs.php

App_Catalog_Block_Category_View
→ /app/code/local/App/Catalog/Block/Category/View.php

重写Magento控制器(Controller)-正则表达式匹配式

重写Magento控制器我们我们以重写购物车为例。

1、首先在App下创建新的模块,依次创建如下文件:

/app/code/local/App/Shopping
/app/code/local/App/Shopping/etc
/app/code/local/App/Shopping/etc/config.xml
/app/code/local/App/Shopping/controllers
/app/code/local/App/Shopping/controllers/CartController.php

2、编辑/app/code/local/App/Shopping/etc/config.xml文件,加入如下代码:

<?xml version="1.0"?>
<config>
    <modules>
        <App_Shopping>
            <version>0.1.0</version>
        </App_Shopping>
    </modules>
    <global>
        <!-- This rewrite rule could be added to the database instead -->
        <rewrite>
            <!-- This is an identifier for your rewrite that should be unique -->
            <!-- THIS IS THE CLASSNAME IN YOUR OWN CONTROLLER -->
            <App_Shopping_cart>
                <from><![CDATA[#^/checkout/cart/#]]></from>
                <!--
                    - Shopping module matches the router frontname below - checkout_cart
                    matches the path to your controller Considering the router below,
                    "/shopping/cart/" will be "translated" to
                    "/App/Shopping/controllers/CartController.php" (?)
                -->
                <to>/shopping/cart/</to>
            </App_Shopping_cart>
        </rewrite>
    </global>
    <!--
        If you want to overload an admin-controller this tag should be <admin>
        instead, or <adminhtml> if youre overloading such stuff (?)
    -->
    <frontend>
        <routers>
            <App_Shopping>
                <!-- should be set to "admin" when overloading admin stuff (?) -->
                <use>standard</use>
                <args>
                    <module>App_Shopping</module>
                    <!-- This is used when "catching" the rewrite above -->
                    <frontName>shopping</frontName>
                </args>
            </App_Shopping>
        </routers>
    </frontend>
</config>

3、改写你自己的控制器

/app/code/local/App/Shopping/controllers/CartController.php

请将下面的代码添加到你的控制器中,我们唯一修改的地方是在index动作中添加一个error_log();

# 控制器不会自动加载,所以我们需要包含文件,这里与区块(Block)不一样
require_once 'Mage/Checkout/controllers/CartController.php';
class App_Shopping_CartController extends Mage_Checkout_CartController
{
    #覆写indexAction方法
    public function indexAction()
    {
        # Just to make sure
        error_log('成功重写购物车!');
        parent::indexAction();
    }
}

在这段代码中,首先是类名,跟前面讲到的区块(Block)一样,我们自己的类名是App_Shopping_CartController继承原先Mage_Checkout_CartController.在indexAction中我们记录了一段信息。

4、修改App_All.xml,激活我们新的Shopping模块

<?xml version="1.0"?>
<config>
     <modules>
        <App_Catalog>
            <active>true</active>
            <codePool>local</codePool>
        </App_Catalog>
        <App_Shopping>
            <active>true</active>
            <codePool>local</codePool>
        </App_Shopping>
     </modules>
</config>

到这里,清空Magento缓存后,你已经可以看到error_log成功记录了我们的信息,打开页面magentonotes.com/checkout
/cart/,显示的是购物车页面,一切正常,但如果你访问magentonotes.com/shopping/cart/,你会发现是首 页。。。。我们期望的购物车视图还没有出现,如何解决呢?让我们接下来往下看。

5、修改视图文件app/design/frontend/[myinterface]/[mytheme]/layout/checkout.xml

在layout标签中,添加下面内容:

<app_shopping_cart_index>
    <update handle="checkout_cart_index"/>
</app_shopping_cart_index>

注意,这里的大小写敏感。

到这里基本大功告成,但是,我建议你学习下正则表达式,因为刚刚的代码中,有这么一段:


1

<from><
![CDATA[#^/checkout/cart/#]]></
from>

这里是使用正则表达式进行匹配的。

还有一点,经过尝试,这里是可以支持同模块名覆盖的,例如Magento代码中商品详情页是Mage_Catalog_ProductController::viewAction(),如果我们想重写这个Controller,我们可以这样做:

1) 建立新的目录/app/code/local/App/Catalog/controllers/ProductController.php

代码如下:

require_once 'Mage/Catalog/controllers/ProductController.php';

/**
 * Product controller
 *
 * @category   Mage
 * @package    Mage_Catalog
 */
class App_Catalog_ProductController extends Mage_Catalog_ProductController
{
    /**
     * View product action
     */
    public function viewAction()
    {
        echo '覆盖过的....';
        parent::viewAction();
    }
}

2) 编辑/app/code/local/App/Catalog/etc/config.xml,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <App_Catalog>
            <version>0.1.0</version>
        </App_Catalog>
    </modules>
    <global>
        <!-- This rewrite rule could be added to the database instead -->
        <rewrite>
            <!-- This is an identifier for your rewrite that should be unique -->
            <!-- THIS IS THE CLASSNAME IN YOUR OWN CONTROLLER -->
            <App_Shopping_cart>
                <from><![CDATA[#^/catalog/product/#]]></from>
                <!--
                    - Shopping module matches the router frontname below - checkout_cart
                    matches the path to your controller Considering the router below,
                    "/shopping/cart/" will be "translated" to
                    "/App/Shopping/controllers/CartController.php" (?)
                -->
                <to>/catalog/product/</to>
            </App_Shopping_cart>
        </rewrite>
        <blocks>
            <catalog>
                <rewrite>
                        <breadcrumbs>App_Catalog_Block_Breadcrumbs</breadcrumbs>
                </rewrite>
            </catalog>
        </blocks>
    </global>
    <frontend>
        <routers>
            <catalog>
                <use>standard</use>
                <args>
                    <module>App_Catalog</module>
                    <frontName>catalog</frontName>
                </args>
            </catalog>
        </routers>
    </frontend>
</config>

清空Magento缓存,刷新你的商品详情页,看是不是变了,呵呵。但是这个方法有个弊病,你需要把这个模块的所有Controller都复写掉,不然你会遇到比较大的麻烦。说到这,我再介绍一种重写方法.

仔细看配置文件的写法:

<?xml version="1.0"?>
<config>
     <modules>
        <App_Mycms>
            <version>0.1.0</version>
        </App_Mycms>
    </modules>
    <frontend>
        <routers>
            <mycms>
                <use>standard</use>
                <args>
                    <module>App_Mycms</module>
                    <frontName>mycms</frontName>
                </args>
            </mycms>
        </routers>
    </frontend>
    <global>
        <routers>
            <cms>
                <rewrite>
                    <index>
                        <to>App_Mycms/index</to>
                        <override_actions>true</override_actions>
                        <actions>
                           <noroute><to>App_Mycms/index/noroute</to></noroute>
                        </actions>
                    </index>
                </rewrite>
            </cms>
        </routers>
    </global>
</config>

综上所述,三种重写方法都各有千秋,关键看你用在什么地方。另外我们在实践中发现,Magento好像不建议你自己的模块名与现有系统中的模块名一 致,例如Mage_Customer是已有的,它的模块名叫Customer,如果你想复写它,那么最好你再建一个App_Customers之类的。

重写Magento模型和动作助手(Model&Helper)

我们在改写Magento的过程中,为了实现自己的业务逻辑,难免要改它的业务模型。你可以尝试用模块下的配置文件配置你自己的类,继承你想重写的模型或者助手,然后调用自己的类。现在我们以用户模型为例深入讲解。

1) 首先创建自己的模块文件夹

app/code/local/App/Customer
app/code/local/App/Customer/etc/config.xml
app/code/local/App/Customer/Model
app/code/local/App/Customer/Model/Customer.php

2) 修改app/etc/modules/App_All.xml

<App_Customer>
    <active>true</active>
    <codePool>local</codePool>
</App_Customer>

3) 修改自己的模块配置文件app/code/local/App/Customer/etc/config.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <App_Customer>
            <version>0.1.0</version>
        </App_Customer>
    </modules>

    <global>
        <models>
            <customer>
                <rewrite>
                    <customer>App_Customer_Model_Customer</customer>
                </rewrite>
            </customer>
        </models>
    </global>
</config>

4) 现在写你新的Model,在文件app/code/local/App/Customer/Model/Customer.php中新建类App_Customer_Model_Cutomer

class App_Customer_Model_Customer extends Mage_Customer_Model_Customer {
    // 重写已存在的方法
    public function validate() {
        // Define new validate rules. From now magento call this validate method instead of existing method
        //return $errors;
        return true;
    }

    // 你还可以创建新的方法
    public function newMethod() {
        // function logic
    }
}

5) 我们再重写一个类,以加深理解。接下来我们重写Customer Address Model。 跟重写Customer Model一样,我们先编辑模块的配置文件app/code/local/App/Customer/etc/config.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <App_Customer>
            <version>0.1.0</version>
        </App_Customer>
    </modules>

    <global>
        <models>
            <customer>
                <rewrite>
                    <customer>App_Customer_Model_Customer</customer>
                    <address>App_Customer_Model_Address</address>
                </rewrite>
            </customer>
        </models>
    </global>
</config>

上面看出来了么,rewrite标签内的customer和address其实就是你要覆写的magento model。

接下来创建model class App_Customer_Model_Address,并写你要覆盖和新增的方法

class App_Customer_Model_Address extends Mage_Customer_Model_Address {
    // 重写已存在的方法
    public function validate() {
        // Define new validate rules. From now magento call this validate method instead of existing method
        //return $errors;
        return true;
    }

    // 你还可以创建新的方法
    public function newMethod() {
        // function logic
    }
}

6)我再讲下如何覆盖Magento的模型资源,这里以复写Address Entity Model class为例,我们先来修改模块的配置文件app/code/local/App/Customer/etc/config.xml。

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <App_Customer>
            <version>0.1.0</version>
        </App_Customer>
    </modules>

    <global>
        <models>
            <customer>
                <rewrite>
                    <customer>App_Customer_Model_Customer</customer>
                    <address>App_Customer_Model_Address</address>
                </rewrite>
            </customer>
            <customer_entity>
                <rewrite>
                    <address>App_Customer_Model_Entity_Address</address>
                </rewrite>
            </customer_entity>
        </models>
    </global>
</config>

接下来创建类文件

class App_Customer_Model_Entity_Address extends Mage_Customer_Model_Entity_Address {
    protected function _afterSave(Varien_Object $address) {
        // Write your code
    }
}

如何修改、扩展并重写Magento代码

时间: 2024-10-21 10:45:05

如何修改、扩展并重写Magento代码的相关文章

怎样改动、扩展并重写Magento代码

作为一个开发人员的你,肯定要改动Magento代码去适应你的业务需求,可是在非常多时候我们不希望改动Magento的核心代码,这里有非常多原因, 比如将来还希望升级Magento.还想使用很多其它的Magento代码.假设你正在寻找改动Magento代码的最佳方式,那么此篇文章将会是一个不错的教程. 适合对象:高级开发人员 适合目标:开发人员希望自己定义改动Magento 当前版本号:Magento versions: 1.4.0.1 作者:精东 重写Magento模块(Module) 第一步,

为原始表添加或修改扩展表Extends table

疫情期间也发个帖子,证明我们依旧小强. 免责声明: 如果你创建了一个新表后发现没有扩展自某表,建议删除重建,删除重建需要分别使用两个update set保存,否则更新到UAT或者PROD环境看不到,后果请自负. 使用代码添加或修改扩展表是不被Servicenow公司赞同的,如果你的表在创建后已经有很多功能了,担心数据问题,建议还是找SN公司,提一个ticket就能解决.如果直接使用本代码,造成数据不匹配等等问题,后果自负(SN也是这么说的哈). 首先声明这种做法可以为原始表添加或修改扩展表Ext

EasyUI中datagrid实现显示、增加、 删除、 修改、 查询操作(后台代码C#)

2datagrid加载数据.代码如下所示 一.数据的显示 1新建HtmlPage2.html页面,引入相关文件.如下所示 <script src="easyui/js/jquery-1.8.2.min.js"></script>  <script src="easyui/js/jquery.easyui.min.js"></script>  <link href="easyui/css/themes/d

IOS Ui控件 修改位置和尺寸,代码添加控件

所有的UI控件最终都继承自UIView,UI控件的公共属性都定义在UIView中, UIView的常见属性 UIView *superview; 获得自己的父控件对象 NSArray *subviews; 获得自己的所有子控件对象 NSInteger tag; 控件的ID(标识),父控件可以通过tag来找到对应的子控件 CGAffineTransform transform; 控件的形变属性(可以设置旋转角度.比例缩放.平移等属性) CGRect frame; 控件所在矩形框在父控件中的位置和尺

Magento代码之订单创建流程

Magento代码之订单创建流程         直接看代码吧.下面的代码是如何通过程序创建一个完美订单.        <?php        require_once 'app/Mage.php';                 Mage::app('default');//初始化程序,设置当前店铺                 $store = Mage::app()->getStore('default');        //通过电子邮件获取用户,当然也可以不获取,创建gues

linux批量修改扩展名

问题:查找当前目录及其子目录下所有扩展名为.txt的文件,将其扩展名修改为.html 方法1: rename .txt  .html   *.txt 方法2: find . -type f -name "*.txt" -print0 | xargs -0 rename .txt .html {} 使用find的-print0和 xargs的-0选项,可以解决文件名中包含空格的问题. 方法3: for file in *.html; do mv $file ${file%.html}.t

修改Eclipse与MyEclipse的代码提示功能

本文的目的是修改Eclipse与MyEclipse的代码提示功能,使之能够更加快速的帮助程序员编写代码. 本文使用的Eclipse版本为4.2 JUNO,MyEclipse的版本为10.6. 1. 设置代码自动完成提示的触发键 依次点击Window-->Preferences-->Java-->Editor-->Content Assist: "Auto activation triggers for Java" 指定当按下什么键时,会弹出代码提示.按照自己习惯

原型的实时局部修改与全部重写的区别(原型的动态性)

1 //代码1-原型原理: 2 function Student(){ 3 //创建了一个空的构造函数 4 } 5 6 //注意:创建了函数Student的同时Student.prototype原型对象就立即产生了 7 8 var person1 = new Student();//实例person1默认都会从Student.prototype 继承属性与方法 9 var person2 = new Student();//实例person2默认都会从Student.prototype 继承属性

如何去修改一段陌生的代码

写在这里仅仅是为了备忘 场景: 最近的工作中用到使用ffmpeg实现了一些功能,现在有需求的变更,需要修改(重新组合或者拆分)这些功能. 本人对ffmpeg十分陌生,对我们项目中ffmpeg实现的功能比较熟悉.这是典型的对业务熟,对代码不熟,呵呵. 1.熟悉功能 2.不熟悉实现功能的代码 3.要去修改这些功能(代码) 通过这几天的工作努力完成这项工作.特总结如下: 1.理解功能,对功能根据代码的结构进行细化,比如保存文件细化为 编码 + 保存文件 (功能的细化是根据代码的实现逻辑来的,并不是凭空