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.
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!
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 <admin> instead, or <adminhtml> if youre 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() {
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 :
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:
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.
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.
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:
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?
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.
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:
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.
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…
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}
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?