Showing posts with label Magento Commerce. Show all posts
Showing posts with label Magento Commerce. Show all posts

Tuesday, 16 June 2009
Facebook StumbleUpon Twitter Google+ Pin It

Overriding Controllers and Actions in Magento

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.

-By Parthiv Patel
Parthiv Patel
Bhaishri Info Solution
Sr. PHP Developer
Limdi Chowk, AT PO. Nar, Di. Anand
Nar, Gujarat
388150
India
pparthiv2412@gmail.com
7383343029
DOB: 12/24/1986

Thursday, 2 April 2009
Facebook StumbleUpon Twitter Google+ Pin It

Secret feature of Magento 1.3: Sharing same route name for different modules!

I have already talked about flexible architecture of Magento Commerce in my previous posts. As Magento allows to customize its default behavior without touching and modifying the existing code, we can override any of the existing class by defining our own in our out of the box extensions. I have also played with Magento by creating variety of extensions, and believe me, it was a real fun of programming. Magento allowed me to change everything I desired.

But I was still feeling that something is missing! And that missing thing was provision for sharing of route names which is now available since Magento 1.3 released yesterday. Now, the first question may arise here that "what is sharing of route names?". 'Sharing of route names' is not a functional feature. So if you'll try to find it in Magento features list, you may be disappointed. Actually it is a feature for developers. It is not even mentioned in Magento 1.3 Release Notes. I found this secret feature in newer version of Magento when I was roaming inside the code to search the difference between 1.2 and 1.3. Let me explain this feature in more detail.

Sometimes, I was supposed to develop extensions which required extra pages or forms in existing modules. For example, adding extra features to Admin Panel. I needed some extra controllers and actions for Admin Panel. This seems OK. I could easily create a local module for it as explained in this Wiki. But an uncomfortable part in this way is this configuration:
<admin>
 <routers>
   <sintax>
     <use>admin</use>
     <args>
       <module>Mage_Sintax</module>
       <frontName>sintax</frontName>
     </args>
   </sintax>
 </routers>
</admin>

Here, all URLs of my additional pages will be started by /sintax/ while all other admin panel pages will be started by /admin/. I am forced to use other routes for my additional modules. I cannot just add more URLs to 'admin' route! This can be fare for Admin Panel pages as they will never be visible by public. But what if I want to add more pages to frontend? If I add any extra page to 'catalog' module, I can't define URLs for my pages starting with /catalog/. I have to define a route something like /mycatalog/ which I don't like!

One solution for this to use URL rewrite from /catalog/mypage/ to /mycatalog/mypage/. But unfortunately, URL helpers will still generate URLs like /mycatalog/mypage/.

The problem with the older version of Magento was mapping one to one relationthip with module front name to module real name i.e. 'catalog' => 'Mage_Catalog', 'admin' => 'Mage_Adminhtml' etc. So I could not map my additional module to existing front name. But Magento 1.3 allows to map additional modules to existing front names. How? Just by changing router configuration for module shown above to the following:
<admin>
 <routers>
   <adminhtml>
     <args>
       <modules>
         <sintax before="Mage_Adminhtml">Mage_Sintax</sintax>
       </modules>
     </args>
   </adminhtml>
 </routers>
</admin>
This configutation will add Mage_Sintax module to admin frontname. An attribute before can be added to give more priority then existing module in finding controllers. For example in this case, /admin/catalog/ URL will call a controller class Mage_Sintax_CatalogController, if it is defined and if not then it will call Mage_Adminhtml_CatalogController. Similarly, after attribute will assign less priority then the existing module. We can add as many modules as we need to the same front name using this way.

Sounds good? Then try it yourself...!

-By Parthiv Patel
Parthiv Patel
Bhaishri Info Solution
Sr. PHP Developer
Limdi Chowk, AT PO. Nar, Di. Anand
Nar, Gujarat
388150
India
pparthiv2412@gmail.com
7383343029
DOB: 12/24/1986