作为一个开发人员的你,肯定要改动Magento代码去适应你的业务需求,可是在非常多时候我们不希望改动Magento的核心代码,这里有非常多原因, 比如将来还希望升级Magento、还想使用很多其它的Magento代码。假设你正在寻找改动Magento代码的最佳方式,那么此篇文章将会是一个不错的教程。
适合对象:高级开发人员
适合目标:开发人员希望自己定义改动Magento
当前版本号:Magento versions: 1.4.0.1
作者:精东
第一步,你须要创建属于你自己代码的命名空间,比如MagentoNotes,App等,为了方便与大家分享代码,我将空间命名为App。
app/ code/ core/ community/ local/ App/
app/ code/ core/ community/ local/ App/ Catalog/ Block/ Breadcrumbs.php etc/ config.xml
创建文件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,以下我们通过模块的配置文件来实现。
编辑文件“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> <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控制器我们我们以重写购物车为例。
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
<?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>
# 控制器不会自己主动载入,所以我们须要包括文件,这里与区块(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>
到这里,清空Magento缓存后,你已经能够看到error_log成功记录了我们的信息,打开页面magentonotes.com/checkout /cart/,显示的是购物车页面,一切正常,但假设你訪问magentonotes.com/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>
注意,这里的大写和小写敏感。
到这里基本大功告成,可是,我建议你学习下正則表達式,由于刚刚的代码中,有这么一段:
1
|
<
from
>< ![CDATA[#^/checkout/cart/#]]></
from
>
|
这里是使用正則表達式进行匹配的。
另一点,经过尝试,这里是能够支持同模块名覆盖的,比如Magento代码中商品详情页是Mage_Catalog_ProductController::viewAction(),假设我们想重写这个Controller,我们能够这样做:
1) 建立新的文件夹/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(); } }
<?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>
<?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的过程中,为了实现自己的业务逻辑,难免要改它的业务模型。你能够尝试用模块下的配置文件配置你自己的类,继承你想重写的模型或者助手,然后调用自己的类。如今我们以用户模型为例深入解说。
1) 首先创建自己的模块目录
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
<App_Customer> <active>true</active> <codePool>local</codePool> </App_Customer>
<?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>
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 } }
<?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>
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 } }
<?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 } }