天机不可泄漏也

我有书半卷

导航

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

转自:http://www.magentonotes.com

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

适合对象:高级开发者

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

当前版本:Magento versions: 1.4.0.1

重写Magento模块(Module)

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

1 app/
2   code/
3    core/
5    community/
6       local/
7         App/

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

 1 app/
2 code/
3   core/
4 community/
5 local/
6   App/
7   Catalog/
8   Block/
9    Breadcrumbs.php
10 etc/
11 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 App_Catalog_Block_Breadcrumbs → /app/code/local/App/Catalog/Block/Breadcrumbs.php
2 App_Catalog_Block_Category_View → /app/code/local/App/Catalog/Block/Category/View.php

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

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

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

1 /app/code/local/App/Shopping
2 /app/code/local/App/Shopping/etc
3 /app/code/local/App/Shopping/etc/config.xml
4 /app/code/local/App/Shopping/controllers
5 /app/code/local/App/Shopping/controllers/CartController.php

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

 1 <?xml version="1.0"?>
2 <config>
3 <modules>
4 <App_Shopping>
5 <version>0.1.0</version>
6 </App_Shopping>
7 </modules>
8 <global>
9 <!-- This rewrite rule could be added to the database instead -->
10 <rewrite>
11 <!-- This is an identifier for your rewrite that should be unique -->
12 <!-- THIS IS THE CLASSNAME IN YOUR OWN CONTROLLER -->
13 <App_Shopping_cart>
14 <from><![CDATA[#^/checkout/cart/#]]></from>
15 <!--
16 - Shopping module matches the router frontname below - checkout_cart
17 matches the path to your controller Considering the router below,
18 "/shopping/cart/" will be "translated" to
19 "/App/Shopping/controllers/CartController.php" (?)
20 -->
21 <to>/shopping/cart/</to>
22 </App_Shopping_cart>
23 </rewrite>
24 </global>
25 <!--
26 If you want to overload an admin-controller this tag should be <admin>
27 instead, or <adminhtml> if youre overloading such stuff (?)
28 -->
29 <frontend>
30 <routers>
31 <App_Shopping>
32 <!-- should be set to "admin" when overloading admin stuff (?) -->
33 <use>standard</use>
34 <args>
35 <module>App_Shopping</module>
36 <!-- This is used when "catching" the rewrite above -->
37 <frontName>shopping</frontName>
38 </args>
39 </App_Shopping>
40 </routers>
41 </frontend>
42 </config>

3、改写你自己的控制器
/app/code/local/App/Shopping/controllers/CartController.php
请将下面的代码添加到你的控制器中,我们唯一修改的地方是在index动作中添加一个error_log();

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

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

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

 1 <?xml version="1.0"?>
2 <config>
3 <modules>
4 <App_Catalog>
5 <active>true</active>
6 <codePool>local</codePool>
7 </App_Catalog>
8 <App_Shopping>
9 <active>true</active>
10 <codePool>local</codePool>
11 </App_Shopping>
12 </modules>
13 </config>

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

5、修改视图文件app/design/frontend/[myinterface]/[mytheme]/layout/checkout.xml
在layout标签中,添加下面内容:

1 <app_shopping_cart_index>
2 <update handle="checkout_cart_index"/>
3 </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
代码如下:

 1 require_once 'Mage/Catalog/controllers/ProductController.php';
2
3 /**
4 * Product controller
5 *
6 * @category Mage
7 * @package Mage_Catalog
8 */
9 class App_Catalog_ProductController extends Mage_Catalog_ProductController
10 {
11 /**
12 * View product action
13 */
14 public function viewAction()
15 {
16 echo '覆盖过的....';
17 parent::viewAction();
18 }
19 }

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都复写掉,不然你会遇到比较大的麻烦。说到这,我再介绍一种重写方法.
仔细看配置文件的写法:

 1 <?xml version="1.0"?>
2 <config>
3 <modules>
4 <App_Mycms>
5 <version>0.1.0</version>
6 </App_Mycms>
7 </modules>
8 <frontend>
9 <routers>
10 <mycms>
11 <use>standard</use>
12 <args>
13 <module>App_Mycms</module>
14 <frontName>mycms</frontName>
15 </args>
16 </mycms>
17 </routers>
18 </frontend>
19 <global>
20 <routers>
21 <cms>
22 <rewrite>
23 <index>
24 <to>App_Mycms/index</to>
25 <override_actions>true</override_actions>
26 <actions>
27 <noroute><to>App_Mycms/index/noroute</to></noroute>
28 </actions>
29 </index>
30 </rewrite>
31 </cms>
32 </routers>
33 </global>
34 </config>

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

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

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

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

1 app/code/local/App/Customer
2 app/code/local/App/Customer/etc/config.xml
3 app/code/local/App/Customer/Model
4 app/code/local/App/Customer/Model/Customer.php

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

1 <App_Customer>
2 <active>true</active>
3 <codePool>local</codePool>
4 </App_Customer>

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

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <config>
3 <modules>
4 <App_Customer>
5 <version>0.1.0</version>
6 </App_Customer>
7 </modules>
8
9 <global>
10 <models>
11 <customer>
12 <rewrite>
13 <customer>App_Customer_Model_Customer</customer>
14 </rewrite>
15 </customer>
16 </models>
17 </global>
18 </config>

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

 1 class App_Customer_Model_Customer extends Mage_Customer_Model_Customer {
2 // 重写已存在的方法
3 public function validate() {
4 // Define new validate rules. From now magento call this validate method instead of existing method
5 //return $errors;
6 return true;
7 }
8
9 // 你还可以创建新的方法
10 public function newMethod() {
11 // function logic
12 }
13 }

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

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <config>
3 <modules>
4 <App_Customer>
5 <version>0.1.0</version>
6 </App_Customer>
7 </modules>
8
9 <global>
10 <models>
11 <customer>
12 <rewrite>
13 <customer>App_Customer_Model_Customer</customer>
14 <address>App_Customer_Model_Address</address>
15 </rewrite>
16 </customer>
17 </models>
18 </global>
19 </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。

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <config>
3 <modules>
4 <App_Customer>
5 <version>0.1.0</version>
6 </App_Customer>
7 </modules>
8
9 <global>
10 <models>
11 <customer>
12 <rewrite>
13 <customer>App_Customer_Model_Customer</customer>
14 <address>App_Customer_Model_Address</address>
15 </rewrite>
16 </customer>
17 <customer_entity>
18 <rewrite>
19 <address>App_Customer_Model_Entity_Address</address>
20 </rewrite>
21 </customer_entity>
22 </models>
23 </global>
24 </config>

接下来创建类文件

1 class App_Customer_Model_Entity_Address extends Mage_Customer_Model_Entity_Address {
2 protected function _afterSave(Varien_Object $address) {
3 // Write your code
4 }
5 }

posted on 2011-08-30 13:38  天机不可泄漏也  阅读(1409)  评论(1编辑  收藏  举报