How to override a Magento controller

Say I want to override Magento Catalog Product controller, say my namespace is Magex and my module name is Powercat.

Firstly, add the following to Powercat/etc/config.xml. What it does is adding another route “prowercat” in addition to “catalog” to frontend. When http://mydomain/catalog/somecontroller/someaction/ is routered, powercat/somecontroller/someaction will be loaded before (see the attribute “before”?) catalog/somecontroller/someaction. If powercat/somecontroller/someaction is available, people get some page when visiting http://mydomain/catalog/somecontroller/someaction/ or http://mydomain/powercat/somecontroller/someaction/. I will not publish the latter url because the whole point of overriding a controller is reusing the Magento original url.

<?xml version="1.0"?>
<config>
<frontend>
<routers>
<catalog>
<args>
<modules>
<anyname before="Mage_Catalog">Magex_Powercat</anyname><!-- the tag name can be any name -->
</modules>
</args>
</catalog>
</frontend>
</config>

Secondly, create a subclass in the following format. “require_once” is essential because controllers are not auto-loaded.

<?php
require_once 'Mage/Catalog/controllers/SomeController.php';
class Magex_Powercat_SomeController extends Mage_Catalog_SomeController
{
//function someAction here
}
?>

Last but not the least, put the overriding controllers into a dedicated module. Otherwise it is very easy to break Magento fallback mechanism. For example, suppose Magex_Powercat has two controllers.

  1. Magex_Powercat_IndexController does its own logic (not extending Mage_Catalog_IndexController, and
  2. Magex_Powercat_ProductController extends Mage_Catalog_ProductController

The scenarios are:

  • When people visit http://mydomain/catalog/product/someaction/, powercat/somecontroller/someaction will be loaded – OK.
  • When people visit http://mydomain/catalog/category/someaction/, catalog/category/someaction will be loaded (because Powercat does not have CategoryController, Magento will fallback to Mage’s CategoryController) – OK.
  • When people visit http://mydomain/catalog/index/someaction/, if Powercat’s IndexController does not have someAction (only Mage’s IndexController has) – Error happens!
  • When people visit http://mydomain/catalog/index/someaction/, if Powercat’s IndexController does have someAction, page will load without error. However, remember Magex_Powercat_IndexController does its own logic? No router to the original logic!

14 comments

  1. 我曾经一门心思想要 override Magento controller,但发现 Magento 文档里很详细地讲了 override model, block, helper 的规则,对 override controller 有意无意地很少谈及。我 trial and error 了很久才摸索出它的习性,不过,如今想来,override Magento controller 应该作为没有办法后的办法,there are always other ways around.

  2. Hi 你好,
    我想要 override Catalog/ProductController,依照了你的方式还是不行。那个anyname没有关系的吗?
    能不能把config.xml完整的贴出让我参考?谢谢。。

  3. 文中的 config.xml 就是完整的。估计你的问题不是出在 config,你可以把整个 module 发给我,如果不复杂的话,我帮你诊断一下

  4. 看来你未得我文中的精髓:尽量不要override controller。比如说,加个新action在ProductController,表面上看,跟product有关的action都在一个controller里,显得很有条理,但override controller以后有很大副作用。

    建议新建一个controller,叫PowerProductController也好,叫MyProductController也好,都比override controller容易调试。

    如果你还是坚持override controller,那就把文件打包给我吧,我的邮箱已另行回复给你。

  5. 刚刚把文件传给你了,只是一个ProductController.php。

    config.xml的内容就是如你所给的例子一样,只是换了Module名字

    Neumann_Catalog

  6. 你好我照着你的config。xml配置了一下但是好像不能生效,这个方法在1.4里面还生效吗?

  7. 可以了,原来把modules 写成module了
    我还有个问题想请教一下;我怎么样可以得知parent action是否执行成功呢?就能用户注册来说吧。我想做一个判断,如果成功的话就显示一些东西,否则显示其他东西。有办法直接得到parent action的执行结果么?好像action没有return值,谢谢了

  8. 我复查了,我用的是<modules>。或许<module>也成,没测试。

    action 通常没有返回值,就算有,也是指 front controller 是否 dispatch 成功。要判断用户注册是否成功,要到 model 里去找响应的方法。在 controller 此类的返回值,有点缘木求鱼。你可以逆向思考:一个 action 可以执行多项操作,就算 action 有返回值,能代表多项操作的哪几项呢?

  9. 用了您的方法,不成功。
    我也想重写一下ProductController的view方法
    XML是这样配置的

    0.1.0

    xxx_SaveInfo

    我的ProductController是这样
    require_once ‘Mage/Catalog/controllers/ProductController.php’;
    //require_once Mage::getModuleDir(‘controllers’, ‘Mage_Catalog’).DS.’ProductController.php’;

    class xxx_SaveInfo_ProductController extends Mage_Catalog_ProductController
    {
    public function viewAction()
    {
    echo “ddddddddddddddddddddddddddddddddd”;

    }
    }

    求解,真心感谢

Leave a comment

Your email address will not be published. Required fields are marked *