做爲一個開發者的你,確定要修改Magento代碼去適應你的業務需求,可是在不少時候咱們不但願修改Magento的核心代碼,這裏有不少緣由, 例如未來還但願升級Magento、還想使用更多的Magento代碼。若是你正在尋找修改Magento代碼的最佳方式,那麼此篇文章將會是一個不錯的教程。php
第一步,你須要建立屬於你本身代碼的命名空間,例如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
編輯文件「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控制器咱們咱們以重寫購物車爲例。
一、首先在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 }
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的過程當中,爲了實現本身的業務邏輯,不免要改它的業務模型。你能夠嘗試用模塊下的配置文件配置你本身的類,繼承你想重寫的模型或者助手,而後調用本身的類。如今咱們以用戶模型爲例深刻講解。
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 }