第九章-修改、擴展、重寫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,是他們對待工作的熱情和責任感促使我寫這些教程。

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