重寫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';
- /**
- * Product controller
- *
- * @category Mage
- * @package Mage_Catalog
- */
- class App_Catalog_ProductController extends Mage_Catalog_ProductController
- {
- /**
- * View product action
- */
- 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,是他們對待工作的熱情和責任感促使我寫這些教程。