Google
 

Wednesday, June 17, 2009

Overriding Controllers and Actions in Magento

In my previous post, I had explained a way to add extra controllers to existing route. Here I am going to explain another method which is used for overriding controllers and actions. Like my each post on tips & tricks, I am going to first explain where the trick is applicable! I am considering that readers of this post are aware of MVC architecture in Magento.

Let me explain the difference between the both tricks. The trick explained in previous post is used when we need additional URLs in same route i.e. additional controllers and actions. I have already explained an example there. Here we need to change the behavior of existing controller and action. For example, when a customer adds a product to shopping cart, addAction of CartController of Mage_Checkout module is called. If we want to override this by My_Checkout, MycartController, myaddAction as similarly as we can override Models and Blocks in our own modules. So the the trick in previous post is used for overloading while the trick here is used for overriding.

Of course, this too can be done just by simple XML configuration (apart from creating custom controllers and actions) but without using route rewriting approach! Let's take a same example above where we want to override action for checkout/cart/add. First create My_Checkout module with MycartController class and myaddAction method defined within it. The way to do this is better explained in this wiki. Then the configuration required in etc/config.xml of My_Checkout module is like below:
<global>
  <routers>
    <checkout> <!-- Mage_Checkout module -->
      <rewrite>
        <cart> <!-- CartController -->
          <to>mycheckout/mycart</to> <!-- My_Checkout module, MycartController -->
          <override_actions>true</override_actions>
          <actions>
            <add> <!-- addAction -->
              <to>mycheckout/mycart/myadd<to> <!-- My_Checkout/MycartController/myaddAction -->
            </add>
          </actions>
        </cart>
      </rewrite>
    </checkout>
  </routers>
</global>
Here we also need configuration to define module front name for My_Checkout module as below:
<frontend>   <!-- It will be admin for overriding admin controller -->
  <routers>
    <mycheckout>
      <use>admin</use>
      <args>
        <module>My_Checkout</module>
        <frontName>mycheckout</frontName>
      </args>
    </mycheckout>
  </routers>
</frontend>   <!-- It will be admin for overriding admin controller -->
Note: The above configuration examples only display portions of config.xml file. Please do not consider it as a complete configuration.

Simple isn't it? Now let's understand how it works. The work flow of this rewrite process is little bit tricky.
  1. When an checkout/cart/add action is going to be dispatched, first it is passed through rewrite process.
  2. Rewrite process tries to find global/routers/checkout/rewrite/cart node is found in configuration, where checkout is front name of Mage_Checkout module and cart indicates Mage_Checkout_CartController.
  3. If this node is not found, rewrite process is not be continued and returned to dispatch process. So the action is executed normally. Otherwise, rewrite process is continued.
  4. Now, under this node, it tries to find whether override_actions node is true or false. By default value of override_actions is true. So if it is not added in configuration, it is considered as true.
  5. If override_actions is true, it overrides all actions of Mage_Checkout_CartController with same actions of My_Checkout_MycartController as defined by to node value mycheckout/mycart. For example, if we have defined addAction and indexAction methods inside My_Checkout_MycartController, then it automatically overrides both addAction and indexAction of Mage_Checkout_CartController. In short using to node and override_actions node we can override whole controller instead of individual actions.
  6. If actions/add node is defined where, add indicates addAction of Mage_Checkout_CartController, then override_actions node value is not considered and overrides action by value of actions/add/to node which is mycheckout/mycart/myadd i.e. My_Checkout module, My_Checkout_Mycontroller and myaddAction. So we can also override individual actions by this type of configuration.
Sounds good again? Try it too...

15 comments:

  1. http://www.magentocommerce.com/wiki/how_to_overload_a_controller

    ReplyDelete
  2. @Phil: Thanks for the reference.
    I have already mentioned that link in my post. But the way explained on that link uses URL rewriting approach which causes improper URL generation by using Mage::helper('mymodule')->url('*/*/action').

    Your suggestions are always accepted.

    ReplyDelete
  3. Hi Paryank,

    thank you for your tutorial!!
    I'm trying to use your suggestions in order to override the loginPost action (I need to make a call to a web service before authenticate a user).

    I created a module in local dir with the following files: Companyname/MyCustomer/controllers/AccountController.php;
    Companyname/MyCustomer/etc/config.xml

    In config.xml I put this code:
    global>
    routers>
    customer>
    rewrite>
    account>
    to>companyname/myCustomer/account/to>
    override_actions>false/override_actions>
    actions>
    loginPost>
    to>companyname/myCustomer/account/loginPost/to>
    /loginPost>
    /actions>
    /account>
    /rewrite>
    /customer>
    /routers>
    /global>

    The module is active but when I submit the login form, the default loginPost action is executed.

    Don't know if it matters but the Companyname_MyCustomer_AccountController extends Mage_Customer_AccountController.

    Can you help me?

    Thanks

    ReplyDelete
  4. @lionel:

    The configuration I have mentioned in example is just a portion of config.xml file please do not consider it as full configuration file. You also need to add other basic configurations.

    I have recently edited the post and added another configuration example which is required for custom module. I should have mentioned this while posting this entry but I missed it. :(

    Also refer this wiki first and add required elements in configuration file.

    ReplyDelete
  5. if I want to override saveBillingAction(), is the correct XML-Tag <savebilling> or <saveBilling> ?

    ReplyDelete
  6. @Julian: To override saveBillingAction, it should be defined as <saveBilling> instead of <savebilling>.

    ReplyDelete
  7. Your blog keeps getting better and better! Your older articles are not as good as newer ones you have a lot more creativity and originality now keep it up!

    ReplyDelete
  8. It is very interestingly written, to the author thanks.

    ReplyDelete
  9. Hi,

    have you tried this tutorial with Magento EE 1.7 or Magento SE 1.4?

    I can't override saveBilling action of OnepageController. When I click on the "next" button to save the billing information in the onepage checkout process, I'm redirected to the cart page.

    I didn't change anything, just upgraded from Magento EE 1.6 to Magento EE 1.7 (and this customization works perfectly with Magento EE 1.6).

    Have you experienced the same problem?

    Thanks a lot

    Fabrizio

    ReplyDelete
  10. @Fabrizo: I haven't tried it on Magento EE. But it works with Magento SE 1.4. Please feel free to share your ideas if you have.

    ReplyDelete
  11. hi

    you are here, thanks for good post related to overriding

    ReplyDelete
  12. Hi I trying to implement external web service in magento and also tried to integrate paypal express with external web service by inserting paypal response value in web service tables in magento database.

    But i am not able insert those value in database.

    So please help me for inserting value in external database tables

    ReplyDelete
  13. Thanks this is so simple after read your post.
    I found the best guideline here.
    Thanks for give me.

    ReplyDelete
  14. Wow! Great! After reading your post, i got most of the answers to my questions. Please continue this. I have a question, i will like to overide customer module to give the pages new look - that is, if acustomer log in the account, he/she should a different page design. Can you please help me on the right track?

    Best Regards

    ReplyDelete
  15. Really useful post on overriding. As i am new in this field This is very helpful for me.
    Thanks for sharing.

    ReplyDelete