做为一个开发者的你,确定要修改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 }