(博主提示:本章应该不是原作者的第九章,仅作补充和参考)

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

适合对象:高级开发者

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

当前版本:Magento versions: 1.4.0.1

作者:精东

最后修改时间:2010年7月13日

版本:V 0.3.0

重写Magento模块(Module)

第一步,你需要创建属于你自己代码的命名空间,例如Wemvc,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根本不会理睬你。
举例来说:

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

< ?php
# 控制器不会自动加载,所以我们需要包含文件,这里与区块(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>

到这里,清除缓存后,你已经可以看到error_log成功记录了我们的信息,打开页面http://www.wemvc.dev/checkout/cart/,显示的是购物车页面,一切正常,但如果你访问http://www.wemvc.dev/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>

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

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

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

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

还有一点,经过尝试,这里是可以支持同模块名覆盖的,例如Magento代码中商品详情页是Mage_Catalog_ProductController::viewAction(),如果我们想重写这个Controller,我们可以这样做:
a.简历新的目录/app/code/local/App/Catalog/controllers/ProductController.php
代码如下:

require_once 'Mage/Catalog/controllers/ProductController.php';
  class App_Catalog_ProductController extends Mage_Catalog_ProductController
{ public function viewAction()
{
echo '覆盖过的....';
parent::viewAction();
}
}

b.编辑/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>

清空缓存,刷新你的商品详情页,看是不是变了,呵呵。但是这个方法有个弊病,你需要把这个模块的所有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的过程中,为了实现自己的业务逻辑,难免要改它的业务模型。你可以尝试用模块下的配置文件配置你自己的类,继承你想重写的模型或者助手,然后调用自己的类。现在我们以用户模型为例深入讲解。

a.首先创建自己的模块文件夹

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

b.修改app/etc/modules/App_All.xml

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

c.修改自己的模块配置文件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>

d.现在写你新的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
}
}

e.我们再重写一个类,以加深理解。接下来我们重写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
}
}

f.我再讲下如何覆盖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代码对你来说已经不是难事了。文章至此,要恭喜你,你已经掌握了大部分修改Magento的技能。下面的文章我们会进行更深入的研究。最后感谢所有Sasacake Team Member,是他们对待工作的热情和责任感促使我写这些教程。

深入理解Magento-第九章-修改、扩展、重写Magento代码的更多相关文章

  1. 深入理解MAGENTO – 第九章 – 数据集合瓦瑞恩

    本来,作为一个PHP程序员,如果你想攒一组变量的相关你有一个选择,古老的 阵列 . 尽管共享一个地址的名称与C存储器的阵列,一个PHP数组是一种通用的字典可变数组索引像数值对象结合行为的影响. 在其他 ...

  2. 深入理解计算机系统 第九章 虚拟内存 Part1 第二遍

    这次花了4小时40分钟,看了第 559~575 页,共 17 页 第一遍对应地址 https://www.cnblogs.com/stone94/p/10264044.html 注意:本章的练习题一定 ...

  3. 发现《深入理解C++11》中扩展的friend代码的错误

    目前在总结现代C++的新特性,看了<深入理解C++11>这本书. 今天看到扩展的friend语法这一节,遇到了问题.本节电子版内容参见:https://book.2cto.com/2013 ...

  4. 【机器学习实战 第九章】树回归 CART算法的原理与实现 - python3

    本文来自<机器学习实战>(Peter Harrington)第九章"树回归"部分,代码使用python3.5,并在jupyter notebook环境中测试通过,推荐c ...

  5. 深入理解Magento - 第一章 - Magento强大的配置系统

    深入理解Magento 作者:Alan Storm翻译:zhlmmc 前言第一章 - Magento强大的配置系统第二章 - Magento请求分发与控制器第三章 - 布局,块和模板第四章 - 模型和 ...

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

    作为一个开发人员的你,肯定要改动Magento代码去适应你的业务需求,可是在非常多时候我们不希望改动Magento的核心代码,这里有非常多原因, 比如将来还希望升级Magento.还想使用很多其它的M ...

  7. 通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账号--锁定次数--菜单功能'menufile

      通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁 ...

  8. 《深入理解java虚拟机》读书笔记八——第九章

    第九章 类加载及执行子系统的案例与实战 Q:如果有10个WEB应用程序都是用Spring来进行组织管理的话,可以把Spring放到Common或Shared目录下(Tomcat5.0)让这些程序共享. ...

  9. 第九章:四大组件之Broadcast Receiver

    第九章:四大组件之Broadcast Receiver   一.广播的功能和特征 广播的生命周期很短,经过调用对象-->实现onReceive-->结束,整个过程就结束了.从实现的复杂度和 ...

随机推荐

  1. Zip函数(Python)

    >>> z = zip((2,3,4),(33,44,55)) >>> z <zip object at 0x1022cdb88> >>&g ...

  2. NORDIC内核ARM蓝牙芯片NRF51802/NRF51822

    Nordic  nRF51 系列的IC 和协议堆栈对内存大小.封装类型.接口.周边产品及无线连接提供更多选择. 关于 nRF51 系列 多协议 2.4GHz 射频收发器拥有高性能.超低功耗以及灵活性等 ...

  3. mac 格式化U盘

    作者:Bailm链接:https://www.zhihu.com/question/27888608/answer/486347894来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  4. Struts2 简单的增删改查

    1:主页面 <a href="emp-list">emp-list</a> <br> 然后到struts.xml文件中找到对应的emp-list ...

  5. pic16f877a的AD实验学习

    一.主函数 //采集AD值 #include <pic.h> #include "ad.h" #include "usart.h" __CONFIG ...

  6. 四轴遥控器ADC部分

    一.ADC参考手册学习 A/D转换可以按单次.连续设置采样:可以一一扫描或间断的对多个ADC通道进行采集. ADC的结果有左对齐和右对齐. ADC的输入时钟不得超过14Mhz,它是由PCLK2经分频产 ...

  7. Database基础(七):部署集群基础环境、MySQL-MMM架构部署、MySQL-MMM架构使用

    一.部署集群基础环境 目标: 本案例要求为MySQL集群准备基础环境,完成以下任务操作: 数据库授权 部署MySQL双主多从结构 配置本机hosts解析记录 方案: 使用4台RHEL 6虚拟机,如下图 ...

  8. VC2010 CString.Format使用报错 error C2664

    error C2664: “void ATL::CStringT<BaseType,StringTraits>::Format(const wchar_t *,...)”: 不能将参数 1 ...

  9. Promise、async、await 异步解决方案

    参考: https://www.cnblogs.com/CandyManPing/p/9384104.html  或  https://www.jianshu.com/p/fe0159f8beb4(推 ...

  10. CSS 提示工具(Tooltip)

    CSS 提示工具(Tooltip) 本文为大家介绍如何使用HTML和CSS来实现提示工具, 提示工具在鼠标移动到制定元素后触发,先看下面示例: 1.基础提示工具代码如下: <!doctye ht ...