Magento Forum

Page 1 of 2
Plea for controller action override tutorial/docs
 
zburnham
Member
 
Avatar
Total Posts:  69
Joined:  2007-11-07
Westborough, MA
 

Could we PLEASE PLEASE PLEASE with a cherry on top have a step-by-step tutorial for overriding a standard Magento controller?

There are a few threads in the forums that talk about overriding helpers, etc, but there doesn’t seem to be a complete set of instructions for overriding a controller.

This seems to be a core necessity for extending/modifying Magento for custom functionality.

Suggestions for information to include:

All XML files that need to be modified and the EXACT code that needs to be put in (and the full paths to them, sometimes the other threads aren’t clear on which file you’re supposed to be modifying.)

File locations and modifications that are necessary for the controller to be recognized.  The best I’ve been able to manage so far is to have the core_url_rewrite SQL table point at a different controller (checkout/cart mapping to mymodule/cart) but the best I’ve been able to do is get a ‘404 Not Found 1’ page.

Thanks in advance for any help.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Mark_Kimsal
Sr. Member
 
Total Posts:  186
Joined:  2007-09-12
Michigan, USA
 

I second that.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Jonathan Hedrén
Member
 
Total Posts:  67
Joined:  2007-08-31
Sweden
 

I’ll give you an example. I’m not sure I’m doing it by the book all the time and some things are not a 100% clear to me, but what the heck, it works! smile

In this example I’m overloading Mage_Checkout_CartController::indexAction().

1. Create your module folders and files
Magento/app/code/local/MyNameSpace/MyModule/etc/config.xml
Magento/app/code/local/MyNameSpace/MyModule/controllers/Checkout/CartController.php
Magento/app/etc/modules/MyNameSpace_All.xml

2. Edit Magento/app/code/local/MyNameSpace/MyModule/etc/config.xml like this (comments I’m not a 100% sure about are ending with “(?)"):

<?xml version="1.0"?>
<config>
    <
modules>
        <
MyNameSpace_MyModule>
            <
version>0.1.0</version>
        </
MyNameSpace_MyModule>
    </
modules>
    <global>
        <!-- 
This rewrite rule could be added to the database instead -->
        <
rewrite>
            <!-- 
This is an identifier for your rewrite that should be unique -->
            <
mynamespace_mymodule_checkout_cart>
                <
from><![CDATA[#^/checkout/cart/$#]]></from>
                
<!-- 
                    - 
mymodule matches the router frontname below 
                    
checkout_cart matches the path to your controller
                    
                    Considering the router below
"/mymodule/checkout_cart/" will be 
                    
"translated" to "/MyNameSpace/MyModule/controllers/Checkout/Cart.php" (?)
                -->
                <
to>/mymodule/checkout_cart/</to>
            </
mynamespace_mymodule_checkout_cart>
        </
rewrite>
    </global>
    <!-- 
    If 
you want to overload an admin-controller this tag should be <admininstead,
    or <
adminhtml> if you're overloading such stuff (?)
    -->
    <frontend>
        <routers>
            <mynamespace_mymodule>
                <!-- should be set to "admin" when overloading admin stuff (?) -->
                <use>standard</use>
                <args>
                    <module>MyNameSpace_MyModule</module>
                    <!-- This is used when "catching" the rewrite above -->
                    <frontName>mymodule</frontName>
                </args>
            </mynamespace_mymodule>
        </routers>
    </frontend>
</config>

3. Edit Magento/app/code/local/MyNameSpace/MyModule/controllers/Checkout/CartController.php (The only change I’m doing to the indexAction() is adding an error_log())

<?php

# Controllers are not autoloaded so we will have to do it manually: 
require_once 'Mage/Checkout/controllers/CartController.php';

class 
MyNameSpace_MyModule_Checkout_CartController extends Mage_Checkout_CartController
{

    
# Overloaded indexAction
    
public function indexAction()
    
{
        
        
# Just to make sure
        
error_log('Yes, I did it!');
        
        
$cart $this->_getCart();
        
$cart->init();
        
$cart->save();

        
$this->loadLayout();
        
$this->_initLayoutMessages('checkout/session');

        if (
$continueShoppingUrl Mage::getSingleton('checkout/session')->getContinueShoppingUrl(true)) {
        }
//        elseif ($continueShoppingUrl = Mage::helper('catalog')->getLastViewedUrl()) {
//        }
        
else {
            $continueShoppingUrl 
Mage::getUrl();
        
}

        
if ($continueShoppingUrl{
            $this
->getLayout()->getBlock('checkout.cart')->setContinueShoppingUrl($continueShoppingUrl);
        
}

        $this
->renderLayout();
    
}

}

3. Edit Magento/app/etc/modules/MyNameSpace_All.xml to activate your module:

<?xml version="1.0"?>
<config>
    <
modules>
        <
MyNameSpace_MyModule>
            <
active>true</active>
            <
codePool>local</codePool>
        </
MyNameSpace_MyModule>
    </
modules>
</
config>

4. Edit Magento/app/design/frontend/[myinterface]/[mytheme]/layout/checkout.xml and add the following to use the same update handle as before:

<mymodule_checkout_cart_index>
        <
update handle="checkout_cart_index"/>
    </
mymodule_checkout_cart_index>

5. Point your browser to /checkout/cart/, take a look in your php error log and you should find ‘Yes, I did it!’. Hopefully I didn’t forget anything…

 
Magento Community Magento Community
Magento Community
Magento Community
 
zburnham
Member
 
Avatar
Total Posts:  69
Joined:  2007-11-07
Westborough, MA
 
Jonathan Hedrén - 12 February 2008 01:27 PM

I’ll give you an example. I’m not sure I’m doing it by the book all the time and some things are not a 100% clear to me, but what the heck, it works! smile

In this example I’m overloading Mage_Checkout_CartController::indexAction().

(snip)

This does work! Yay!

I put the rewrite command in core_url_rewrite in the database, with an entry that looks like :

INSERT INTO `core_url_rewriteVALUES (6950'mymodule/1''checkout/cart''mymodule/checkout_cart'''0NULL);

I’m not sure why it’s ‘mymodule/checkout_cart’ and not ‘mymodule/checkout/cart’, as that doesn’t seem consistent.  If someone could illuminate me on that one, it’d help a lot.

I also did not have the following in my indexAction() in app/code/local/MyNameSpace/MyModule/controllers/Checkout/CartController.php :

if ($continueShoppingUrl Mage::getSingleton('checkout/session')->getContinueShoppingUrl(true)) {
        }
//        elseif ($continueShoppingUrl = Mage::helper('catalog')->getLastViewedUrl()) {
//        }
        
else {
            $continueShoppingUrl 
Mage::getUrl();
        
}

        
if ($continueShoppingUrl{
            $this
->getLayout()->getBlock('checkout.cart')->setContinueShoppingUrl($continueShoppingUrl);
        
}

so it looks like it isn’t strictly necessary.

Turns out that my problem was a typo rasberry

 
Magento Community Magento Community
Magento Community
Magento Community
 
Mark_Kimsal
Sr. Member
 
Total Posts:  186
Joined:  2007-09-12
Michigan, USA
 
zburnham - 13 February 2008 07:27 AM


This does work! Yay!

I put the rewrite command in core_url_rewrite in the database, with an entry that looks like :

INSERT INTO `core_url_rewriteVALUES (6950'mymodule/1''checkout/cart''mymodule/checkout_cart'''0NULL);

I’m not sure why it’s ‘mymodule/checkout_cart’ and not ‘mymodule/checkout/cart’, as that doesn’t seem consistent.  If someone could illuminate me on that one, it’d help a lot.

This happens all the time in magento stuffs.  If you were to use

"mymodule/checkout/cart"
you would be referencing an xml tag structure like:
<mymodule>
     <
checkout>
           <
cart>
              
stuffs
           
</cart>
      </
checkout>
</
mymodule>
And that would just be silly… i guess.

The module is always separated by a slash, then the sub-complete name of the class is referenced by underscores.  Like MyMod_Model_Domain_Code would be “mymod/domain_code”.  Depending on what config value you specify, the system automatically pushes “model”, “block”, “controller”, or “helper” between the names for you.  So you can’t put a helper where a block should be, etc.

"mymodule/domain_code"
would be
<mymodule>
      <
models>
            <
domain_code>
                
stuffs
              
</domain_code>
        </
models>
</
mymodule>

This allows you to organize your code into any set of sub-dirs under the main “Model”, “Block”, “Helpers”, etc w/o over-complicating the XML tag structure.  Once you’re in a model or router the system has what it needs to know, everything else is just directory layout.

 
Magento Community Magento Community
Magento Community
Magento Community
 
zburnham
Member
 
Avatar
Total Posts:  69
Joined:  2007-11-07
Westborough, MA
 
Mark_Kimsal - 13 February 2008 09:03 AM


"mymodule/domain_code"
would be
<mymodule>
      <
models>
            <
domain_code>
                
stuffs
              
</domain_code>
        </
models>
</
mymodule>

This allows you to organize your code into any set of sub-dirs under the main “Model”, “Block”, “Helpers”, etc w/o over-complicating the XML tag structure.  Once you’re in a model or router the system has what it needs to know, everything else is just directory layout.

That does help.  So from the above, the way to reference that model would be something like:

Mage::getModel('mymodule/domain_code')

Am I right on that?

 
Magento Community Magento Community
Magento Community
Magento Community
 
perlinux
Jr. Member
 
Total Posts:  4
Joined:  2008-01-22
 
zburnham - 13 February 2008 07:27 AM

This does work! Yay!

I put the rewrite command in core_url_rewrite in the database, with an entry that looks like :

INSERT INTO `core_url_rewriteVALUES (6950'mymodule/1''checkout/cart''mymodule/checkout_cart'''0NULL);

I copied and pasted the example too (using 0.7.15480) but I only get 404.
I checked if I had any typo but didn’t find anything.
The only difference from the example is that I modified “app/design/frontend/default/default/layout/checkout.xml”
for “.../frontend/[myinterface]/[mytheme]/layout/checkout.xml” in the example.

Can you suspect anything that I might be doing wrong?

 
Magento Community Magento Community
Magento Community
Magento Community
 
Jonathan Hedrén
Member
 
Total Posts:  67
Joined:  2007-08-31
Sweden
 
Mark_Kimsal - 13 February 2008 09:03 AM

The module is always separated by a slash, then the sub-complete name of the class is referenced by underscores.  Like MyMod_Model_Domain_Code would be “mymod/domain_code”.  Depending on what config value you specify, the system automatically pushes “model”, “block”, “controller”, or “helper” between the names for you.  So you can’t put a helper where a block should be, etc.

"mymodule/domain_code"
would be
<mymodule>
      <
models>
            <
domain_code>
                
stuffs
              
</domain_code>
        </
models>
</
mymodule>

This allows you to organize your code into any set of sub-dirs under the main “Model”, “Block”, “Helpers”, etc w/o over-complicating the XML tag structure.  Once you’re in a model or router the system has what it needs to know, everything else is just directory layout.

Also, if you want to point directly at a method (in your rewrite rule for example) you can add another “level” like this:

/mymodule/domain_code/mymethod
 
Magento Community Magento Community
Magento Community
Magento Community
 
zburnham
Member
 
Avatar
Total Posts:  69
Joined:  2007-11-07
Westborough, MA
 
perlinux - 13 February 2008 12:12 PM

I copied and pasted the example too (using 0.7.15480) but I only get 404.
I checked if I had any typo but didn’t find anything.
The only difference from the example is that I modified “app/design/frontend/default/default/layout/checkout.xml”
for “.../frontend/[myinterface]/[mytheme]/layout/checkout.xml” in the example.

Can you suspect anything that I might be doing wrong?

Just a thought, try switching [myinterface]/[mytheme] for [mytheme]/[myinterface] .  Also, everything should be lowercase there.

 
Magento Community Magento Community
Magento Community
Magento Community
 
perlinux
Jr. Member
 
Total Posts:  4
Joined:  2008-01-22
 

i just upgraded to 0.8.16100 and now the example worked.
now i can play with the example.
thanks.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Jonathan Hedrén
Member
 
Total Posts:  67
Joined:  2007-08-31
Sweden
 

I added this guide to the wiki: http://www.magentocommerce.com/wiki/how_to_overload_a_controller

 
Magento Community Magento Community
Magento Community
Magento Community
 
bsboard
Jr. Member
 
Total Posts:  15
Joined:  2008-03-18
 

Has anyone gotten this to work with v1? I can’t seem to get it to work, and nobody seems to be responding to my threads when i ask questions.

 
Magento Community Magento Community
Magento Community
Magento Community
 
ralphie
Member
 
Total Posts:  59
Joined:  2007-12-20
London
 

hi, yes it does work in v1. bsboard, check the tutorial of jonathan (i run ver. 1.0.19700). this basic example runs smooth for me. however when i try to overload another function (not the mentioned index one) of this class it still uses the standard core one. does anyone know what i need to change in order it not only uses the index function of the overloaded class?

what i basically want to do is to customize the couponPostAction() function i tried something like that, but no luck yet…

<mymodule_checkout_cart_index>
        <
update handle="checkout_cart_index"/>
<
mymodule_checkout_cart_index
<
mymodule_checkout_cart_couponpost>
        <
update handle="checkout_cart_couponpost"/>
</
mymodule_checkout_cart_couponpost>
 
Magento Community Magento Community
Magento Community
Magento Community
 
Jonathan Hedrén
Member
 
Total Posts:  67
Joined:  2007-08-31
Sweden
 

ralphie: You’ll have to match the url and rewrite it to your routed module (this rewrite could also be done in the db):

...
    <global>
        <
rewrite>
            <
mynamespace_mymodule_checkout_cart>
                <
from><![CDATA[#^/checkout/cart/couponPost$#]]></from>
                
<to>/mymodule/checkout_cart/couponPost</to>
            </
mynamespace_mymodule_checkout_cart>
        </
rewrite>
    </global>
...
 
Magento Community Magento Community
Magento Community
Magento Community
 
ralphie
Member
 
Total Posts:  59
Joined:  2007-12-20
London
 

thanks jonathan for the hint.. was actually just trying something like that when i saw your answer… but no luck. it does not work like that, i get the following error :(

Controller file was loaded but class does not exist
Trace
:
#0 /home/ralph/shop-magento/v1019700/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php(136): Mage::exception('Mage_Core', 'Controller file...')
#1 /home/ralph/shop-magento/v1019700/app/code/core/Mage/Core/Controller/Varien/Front.php(146): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http))
#2 /home/ralph/shop-magento/v1019700/app/Mage.php(427): Mage_Core_Controller_Varien_Front->dispatch()
#3 /home/ralph/shop-magento/v1019700/index.php(53): Mage::run()
#4 {main}

did you get it to work like that on your side?

cheers, ralph

 
Magento Community Magento Community
Magento Community
Magento Community
 
Jonathan Hedrén
Member
 
Total Posts:  67
Joined:  2007-08-31
Sweden
 
ralphie - 20 May 2008 06:25 AM

thanks jonathan for the hint.. was actually just trying something like that when i saw your answer… but no luck. it does not work like that, i get the following error :(

Controller file was loaded but class does not exist
Trace
:
#0 /home/ralph/shop-magento/v1019700/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php(136): Mage::exception('Mage_Core', 'Controller file...')
#1 /home/ralph/shop-magento/v1019700/app/code/core/Mage/Core/Controller/Varien/Front.php(146): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http))
#2 /home/ralph/shop-magento/v1019700/app/Mage.php(427): Mage_Core_Controller_Varien_Front->dispatch()
#3 /home/ralph/shop-magento/v1019700/index.php(53): Mage::run()
#4 {main}

did you get it to work like that on your side?

cheers, ralph

Seems like magento does include your file, but can’t load the class… What is the name of your class and how does your etc/config.xml look like?

 
Magento Community Magento Community
Magento Community
Magento Community
Magento Community
Magento Community
Back to top
Page 1 of 2