I am trying to override a file in Controller and another in controllers directory of the Amazon Payments module. I have followed several tutorials with no luck at overriding the controllers and I have no idea how to override abstract classes in the Controller folder (capital C). I need to override two methods found in two different files indexAction() in OnepageController.php and _getOnepage() in Checkout.php.
app/code/community/Amazon/Payments/controllers/OnepageController.php
class Amazon_Payments_OnepageController extends Amazon_Payments_Controller_Checkout
{
...
public function indexAction()
{
// placeholder required
}
...
}
app/code/community/Amazon/Payments/Controller/Checkout.php
abstract class Amazon_Payments_Controller_Checkout extends Mage_Checkout_Controller_Action
{
...
protected function _getOnepage()
{
return Mage::getSingleton('checkout/type_onepage');
}
...
}
Does anyone see what I am doing wrong in my code that would get this working? Also does anyone know how to override the Checkout.php file at the bottom?
app/etc/modules/KNG_Amazon/Payments.xml
<?xml version="1.0"?>
<config>
<modules>
<KNG_Amazon_Payments>
<active>true</active>
<codePool>local</codePool>
<depends>
<Amazon_Payments />
</depends>
</KNG_Amazon_Payments>
</modules>
</config>
app/code/local/KNG/Amazon/Payments/etc/config.xml
<?xml version="1.0"?>
<config>
<modules>
<KNG_Amazon_Payments>
<version>1.3.0.1</version>
</KNG_Amazon_Payments>
</modules>
<frontend>
<routers>
<amazon_payments>
<args>
<modules>
<KNG_Amazon_Payments before="Amazon_Payments">KNG_Amazon_Payments</KNG_Amazon_Payments>
</modules>
</args>
</amazon_payments>
</routers>
</frontend>
</config>
app/code/local/KNG/Amazon/Payments/controllers/OnepageController.php
require_once 'Amazon/Payments/controllers/OnepageController.php';
class KNG_Amazon_Payments_OnepageController extends Amazon_Payments_OnepageController
{
public function indexAction()
{
$this->_getOnepage()->savePayment(array(
'method' => 'amazon_payments',
'additional_information' => array(
'order_reference' => $this->getAmazonOrderReferenceId(),
)
));
}
}
As for this last file I don't have any idea how to override it but the change below to the method is what I am wanting from the result.
app/code/local/KNG/Amazon/Payments/Controller/Checkout.php
abstract class KNG_Amazon_Payments_Controller_Checkout extends Amazon_Payments_Controller_Checkout
{
protected function _getOnepage()
{
return Mage::getSingleton('amazon_payments/type_checkout');
}
}
Update: After some research I found out that I no longer need to override Checkout.php file. I like the answer that was given by @fschmengler, explaining the differences so I want to leave it. My problem right now is that my code for OnepageController.php is still not working. Can anyone help with that?
Best Answer
As you noticed, these are two different kinds of controller classes. The actual controllers, loaded by the Magento Router, in
controllers
and abstract controller classes, loaded by the autoloader inController
Controller overrides work as follows:
For each route (like
amazon_payments
in your case), several modules can register their controllers:Amazon_Payments
KNG_Amazon_Payments
and specifies that they should be used beforeAmazon_Payments
.Now for each request that starts with the front name of
amazon_payments
, controllers and actions are searched in this order. A request toamazon_payments/onepage/index
will:app/code/local/KNG/Amazon/Payments/controllers/OnepageController.php
,KNG_Amazon_Payments_OnepageController
contains aindexAction
method, if yes, execute it and stop (if this class is not defined in the file, throw an error)app/code/community/Amazon/Payments/controllers/OnepageController.php
Amazon_Payments_OnepageController
contains aindexAction
method, if yes, execute it and stop (if this class is not defined in the file, throw an error)noroute
action (i.e. show 404 page)Abstract
Controller
classes:For abstract controller classes, this override system does not work, you would have to override each single controller and extend the original class, so that all actions use your controllers. This is the same problem that we have with changing methods in abstract model classes. To avoid duplicate code, you could use traits.
But there is another option: Since classes in the
Controller
directory are loaded by the autoloader, the directory fallback system can be used. Place your modified abstract controller inapp/code/local/Amazon/Payments/Controller/Checkout.php
. It must be a modified copy of the original class, not a new class that extends it.Both solutions are not very pretty, but if you really need to make changes there, you have to choose the lesser of the two evils.
Think about it twice, if you can accomplish your goal with a different method. If the code in the question is your real and complete code, maybe you can override the singleton instead?