第九章-修改、扩展、重写Magento代码

重写Magento模块(Module)

 

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

C代码  收藏代码
  1. app/  
  2.      code/  
  3.             core/  
  4.             community/  
  5.             local/  
  6.                     App/  
 

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

C代码  收藏代码
  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代码  收藏代码
  1. < ?xml version="1.0"?>  
  2. <config>  
  3.      <modules>  
  4.         <App_Catalog>  
  5.             <active>true</active>  
  6.             <codePool>local</codePool>  
  7.         </App_Catalog>  
  8.      </modules>  
  9. </config>  
 

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

 

重写Magento区块(Blocks)

 

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

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <config>  
  3.     <modules>  
  4.         <App_Catalog>  
  5.             <version>0.1.0</version>  
  6.         </App_Catalog>  
  7.     </modules>  
  8.     <global>  
  9.         <blocks>  
  10.             <catalog>  
  11.                 <rewrite>  
  12.                         <breadcrumbs>App_Catalog_Block_Breadcrumbs</breadcrumbs>  
  13.                 </rewrite>  
  14.             </catalog>  
  15.         </blocks>  
  16.     </global>  
  17. </config>  
 

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

Xml代码  收藏代码
  1. <blocks>  
  2.           <catalog>  
  3.               <rewrite>  
  4.                       <category_view>App_Catalog_Block_Category_View</category_view>  
  5.               </rewrite>  
  6.           </catalog>  
  7.       </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代码  收藏代码
  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() ;

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

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

 

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

Xml代码  收藏代码
  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>  
 

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

 

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

Xml代码  收藏代码
  1. <app_shopping_cart_index>  
  2.     <update handle="checkout_cart_index"/>  
  3. </app_shopping_cart_index>  
 

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

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

Xml代码  收藏代码
  1. <from>< ![CDATA[#^/checkout/cart/#]]></from>  
 

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

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

 

a.简历新的目录/app/code/local/App/Catalog/controllers/ProductController.php 代码如下:

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

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

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <config>  
  3.     <modules>  
  4.         <App_Catalog>  
  5.             <version>0.1.0</version>  
  6.         </App_Catalog>  
  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[#^/catalog/product/#]]></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>/catalog/product/</to>  
  22.             </App_Shopping_cart>  
  23.         </rewrite>  
  24.         <blocks>  
  25.             <catalog>  
  26.                 <rewrite>  
  27.                         <breadcrumbs>App_Catalog_Block_Breadcrumbs</breadcrumbs>  
  28.                 </rewrite>  
  29.             </catalog>  
  30.         </blocks>  
  31.     </global>  
  32.     <frontend>  
  33.         <routers>  
  34.             <catalog>  
  35.                 <use>standard</use>  
  36.                 <args>  
  37.                     <module>App_Catalog</module>  
  38.                     <frontName>catalog</frontName>  
  39.                 </args>  
  40.             </catalog>  
  41.         </routers>  
  42.     </frontend>  
  43. </config>  
 

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

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

 

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

Xml代码  收藏代码
  1. <App_Customer>  
  2.             <active>true</active>  
  3.             <codePool>local</codePool>  
  4.         </App_Customer>  
 

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

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>  
 

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

Php代码  收藏代码
  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. }  
 

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

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 ,并写你要覆盖和新增的方法

Php代码  收藏代码
  1. class App_Customer_Model_Address extends Mage_Customer_Model_Address {  
  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. }  
 

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

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>  
 

接下来创建类文件。

Php代码  收藏代码
  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. }  
 

总结

 

在本章中我们学习了如何重写模块、重写控制器、重写区块,以及如何重写模型和助手,基本重写Magento代码对你来说已经不是难事了。文章至此, 要恭喜你,你已经掌握了大部分修改Magento的技能。下面的文章我们会进行更深入的研究。最后感谢所有Sasacake Team Member,是他们对待工作的热情和责任感促使我写这些教程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章