【轉載】如何修改、擴展並重寫Magento代碼

    做爲一個開發者的你,確定要修改Magento代碼去適應你的業務需求,可是在不少時候咱們不但願修改Magento的核心代碼,這裏有不少緣由, 例如未來還但願升級Magento、還想使用更多的Magento代碼。若是你正在尋找修改Magento代碼的最佳方式,那麼此篇文章將會是一個不錯的教程。php

重寫Magento模塊(Module)

第一步,你須要建立屬於你本身代碼的命名空間,例如MagentoNotes,App等,爲了方便與你們分享代碼,我將空間命名爲App。html

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,添加以下代碼。app

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,下面咱們經過模塊的配置文件來實現。frontend

重寫Magento區塊(Blocks)

編輯文件「app/code/local/App/Catalog/etc/config.xml」ide

<?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。若是你有更多的目錄層級,能夠用下滑線來分隔。例如:學習

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。ui

在breadcrumbs標籤中的值是你的類名,這樣Magento就能夠獲取你的類,由於類名與你的目錄名一致。用過zend framework的人都知道,自動加載auto loader這個東西,它會跟你類名中的下滑線去你的目錄中須要對應的類文件。記住一點,下滑線表明下一級別的文件夾,若是你的類名與你的文件目錄名不一 致,那麼Magento根本不會理睬你。
舉例來講:this

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控制器咱們咱們以重寫購物車爲例。

一、首先在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

二、編輯/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>

三、改寫你本身的控制器
/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中咱們記錄了一段信息。

四、修改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/,你會發現是首 頁。。。。咱們指望的購物車視圖尚未出現,如何解決呢?讓咱們接下來往下看。

五、修改視圖文件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>

注意,這裏的大小寫敏感。

到這裏基本大功告成,可是,我建議你學習下正則表達式,由於剛剛的代碼中,有這麼一段:

<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,代碼以下:
 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>

清空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,並寫你要覆蓋和新增的方法

 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 }

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 }
相關文章
相關標籤/搜索