作为一个开发者的你,肯定要修改Magento代码去适应你的业务需求,但是在很多时候我们不希望修改Magento的核心代码,这里有很多原因, 例如将来还希望升级Magento、还想使用更多的Magento代码。如果你正在寻找修改Magento代码的最佳方式,那么此篇文章将会是一个不错的教程。
适合对象:高级开发者
适合目标:开发者希望自定义修改Magento
当前版本:Magento versions: 1.4.0.1
作者:精东
重写Magento模块(Module)
第一步,你需要创建属于你自己代码的命名空间,例如MagentoNotes,App等,为了方便与大家分享代码,我将空间命名为App。
1 2 3 4 5 6 | app/ code/ core/ community/ local/ App/ |
假如你现在打算修改Mage/Catalog/Block/Breadcrumbs.php这个文件,你可以在你的命名空间,App里添加一个新的模块 “Catalog”。接下来创建块(Block)目录,并复制Breadcrumbs.php到你的新目录中。这里还需要你创建一个config.xml 配置文件。
1 2 3 4 5 6 7 8 9 10 11 | 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,添加如下代码。
1 2 3 4 5 6 7 8 9 | < ? 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”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <? 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 2 3 4 5 6 7 | < 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根本不会理睬你。
举例来说:
1 2 | 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下创建新的模块,依次创建如下文件:
1 2 3 4 5 | /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文件,加入如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <? 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();
1 2 3 4 5 6 7 8 9 10 11 12 | # 控制器不会自动加载,所以我们需要包含文件,这里与区块(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模块
1 2 3 4 5 6 7 8 9 10 11 12 13 | <? 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 > |
到这里,清空Magento缓存后,你已经可以看到error_log成功记录了我们的信息,打开页面magentonotes.com/checkout /cart/,显示的是购物车页面,一切正常,但如果你访问magentonotes.com/shopping/cart/,你会发现是首 页。。。。我们期望的购物车视图还没有出现,如何解决呢?让我们接下来往下看。
5、修改视图文件app/design/frontend/[myinterface]/[mytheme]/layout/checkout.xml
在layout标签中,添加下面内容:
1 2 3 | < app_shopping_cart_index > < update handle = "checkout_cart_index" /> </ app_shopping_cart_index > |
注意,这里的大小写敏感。
到这里基本大功告成,但是,我建议你学习下正则表达式,因为刚刚的代码中,有这么一段:
1 | < from >< ![CDATA[#^/checkout/cart/#]]></ from > |
这里是使用正则表达式进行匹配的。
还有一点,经过尝试,这里是可以支持同模块名覆盖的,例如Magento代码中商品详情页是Mage_Catalog_ProductController::viewAction(),如果我们想重写这个Controller,我们可以这样做:
1) 建立新的目录/app/code/local/App/Catalog/controllers/ProductController.php
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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(); } } |
2) 编辑/app/code/local/App/Catalog/etc/config.xml,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <? 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 > |
清空Magento缓存,刷新你的商品详情页,看是不是变了,呵呵。但是这个方法有个弊病,你需要把这个模块的所有Controller都复写掉,不然你会遇到比较大的麻烦。说到这,我再介绍一种重写方法.
仔细看配置文件的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <? 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的过程中,为了实现自己的业务逻辑,难免要改它的业务模型。你可以尝试用模块下的配置文件配置你自己的类,继承你想重写的模型或者助手,然后调用自己的类。现在我们以用户模型为例深入讲解。
1) 首先创建自己的模块文件夹
1 2 3 4 | 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 |
2) 修改app/etc/modules/App_All.xml
1 2 3 4 | < App_Customer > < active >true</ active > < codePool >local</ codePool > </ App_Customer > |
3) 修改自己的模块配置文件app/code/local/App/Customer/etc/config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <? 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 > |
4) 现在写你新的Model,在文件app/code/local/App/Customer/Model/Customer.php中新建类App_Customer_Model_Cutomer
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 } } |
5) 我们再重写一个类,以加深理解。接下来我们重写Customer Address Model。 跟重写Customer Model一样,我们先编辑模块的配置文件app/code/local/App/Customer/etc/config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <? 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,并写你要覆盖和新增的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 } } |
6)我再讲下如何覆盖Magento的模型资源,这里以复写Address Entity Model class为例,我们先来修改模块的配置文件app/code/local/App/Customer/etc/config.xml。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <? 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 > |
接下来创建类文件
1 2 3 4 5 | class App_Customer_Model_Entity_Address extends Mage_Customer_Model_Entity_Address { protected function _afterSave(Varien_Object $address ) { // Write your code } } |
原创文章,转载请注明:转载自Web开发笔记 | 如何修改、扩展并重写Magento代码
本文链接地址:https://www.magentonotes.com/overload_magento_controller.html
{ 1 comment }
重写我不是理解的很透 哦想重写有什么好处
Comments on this entry are closed.
{ 3 trackbacks }