[
magento
]
12 May 2015
If you want to modify/ alter some of data in magento with in the default workflow you can achieve this in 2 ways.
- Use an Event
- Override the core model.
Then the big question. What is the best way from above options. Without an argument Event based override is the best option. Because this method is decoupled from the core and will give us a flexibility around upgrading.
We can’t use events all the time. Because Magento got limited events. So in that case we will have to override the the core method to do our job.
##Scenario
Stop custom temporary options get saved against products when adding to cart
***
app/code/core/Mage/Checkout/Model/Cart.php
has addProduct
which is responsible for saving products to the cart.
If you observer the method you can see that there is only one event we can use checkout_cart_product_add_after
, Which is not gong to help in our case as we need to modify $requestInfo
before it get pass in to the $this->_getProductRequest($requestInfo)
.
So as I explained above let’s override the addProduct
. By doing this we can have more flexibility around the code.
Acme/Test/etc/config.xml
<global> <!-- Magento Scope -->
<models>
<checkout> <!-- Core module we want to override -->
<rewrite>
<cart>Acme_Test_Model_Cart</cart> <!-- Module file we want to override -->
</rewrite>
</checkout>
</models>
</global>
Acme/Test/Model/Cart.php
<?php
class Acme_Test_Model_Cart extends Mage_Checkout_Model_Cart
{
/**
* Add product to shopping cart (quote)
*
* @param int|Mage_Catalog_Model_Product $productInfo
* @param mixed $requestInfo
* @return Mage_Checkout_Model_Cart
*/
public function addProduct($productInfo, $requestInfo=null)
{
if (isset($requestInfo['custom_label'])) {
unset($requestInfo['custom_label']);
}
//Keeping the golden rule of Magento in the head
//we passed our modified $requestInfo to the parent method.
//Keep the custom method foot print as small as you can
parent::addProduct($productInfo, $requestInfo);
}
}
[
magento
]
08 Sep 2014
Overriding controllers is bit different to Model/Blocks/Helpers as Controllers do not get loaded though the autoloader.
##Scenario
Send a copy of the mail when a user/visitor submits the contact form.
***
In Magento contact form is handled by Mage_Contacts
. If you take a look at the Mage_Contacts_IndexController
you can find the postAction
method which is responsible for the contact form submission.
In this example we will be overriding the postAction
in Mage_Contacts_IndexController
with Acme_ContactExtended_IndexController
Acme/ContactExtended/etc/config.xml
<frontend> <!-- Magento Area -->
<routers>
<contacts> <!-- Core module we want to override -->
<args>
<modules>
<Acme_ContactExtended before="Mage_Contacts">Acme_ContactExtended</Acme_ContactExtended> <!-- Our custom Controller -->
</modules>
</args>
</contacts>
</routers>
</frontend>
Acme/ContactExtended/controllers/IndexController.php
I haven’t added system.xml in this tutorial and this code might not work if you copy-paste in to you file :). I will explain system.xml
in a different article in the future.
<?php
require_once Mage::getModuleDir('controllers', 'Mage_Contacts') . DS . 'IndexController.php';
class Acme_ContactExtended_IndexController extends Mage_Contacts_IndexController
{
const XML_PATH_SENDER_NOTIFICATION_ENABLED = 'contacts/sender_notification/enabled';
const XML_PATH_SENDER_NOTIFICATION_EMAIL_TEMPLATE = 'contacts/sender_notification/email_template';
public function postAction()
{
$post = $this->getRequest()->getPost();
if ($post) {
$translate = Mage::getSingleton('core/translate');
/* @var $translate Mage_Core_Model_Translate */
$translate->setTranslateInline(false);
try {
$postObject = new Varien_Object();
$postObject->setData($post);
$error = false;
if (!Zend_Validate::is(trim($post['first-name']), 'NotEmpty')) {
$error = true;
}
if (!Zend_Validate::is(trim($post['last-name']), 'NotEmpty')) {
$error = true;
}
if (!Zend_Validate::is(trim($post['email']), 'EmailAddress')) {
$error = true;
}
if (!Zend_Validate::is(trim($post['comment']), 'NotEmpty')) {
$error = true;
}
if (Zend_Validate::is(trim($post['hideit']), 'NotEmpty')) {
$error = true;
}
if ($error) {
throw new Exception();
}
$mailTemplate = Mage::getModel('core/email_template');
/* @var $mailTemplate Mage_Core_Model_Email_Template */
$mailTemplate->setDesignConfig(array('area' => 'frontend'))
->setReplyTo($post['email'])
->sendTransactional(
Mage::getStoreConfig(self::XML_PATH_EMAIL_TEMPLATE),
Mage::getStoreConfig(self::XML_PATH_EMAIL_SENDER),
Mage::getStoreConfig(self::XML_PATH_EMAIL_RECIPIENT),
null,
array('data' => $postObject)
);
if (!$mailTemplate->getSentSuccess()) {
throw new Exception();
}
/* send sender notification */
if (Mage::getStoreConfigFlag(self::XML_PATH_SENDER_NOTIFICATION_ENABLED)) {
$customerMailTemplate = Mage::getModel('core/email_template');
/* @var $mailTemplate Mage_Core_Model_Email_Template */
$customerMailTemplate->setDesignConfig(array('area' => 'frontend'))
->setReplyTo(self::XML_PATH_EMAIL_RECIPIENT)
->sendTransactional(
Mage::getStoreConfig(self::XML_PATH_SENDER_NOTIFICATION_EMAIL_TEMPLATE),
Mage::getStoreConfig(self::XML_PATH_EMAIL_SENDER),
$post['email'],
null,
array('data' => $postObject)
);
if (!$customerMailTemplate->getSentSuccess()) {
throw new Exception();
}
}
/* */
$translate->setTranslateInline(true);
Mage::getSingleton('customer/session')->addSuccess(Mage::helper('contacts')->__('Your inquiry was submitted and will be responded to as soon as possible. Thank you for contacting us.'));
$this->_redirect('*/*/');
return;
} catch (Exception $e) {
$translate->setTranslateInline(true);
Mage::getSingleton('customer/session')->addError(Mage::helper('contacts')->__('Unable to submit your request. Please, try again later'));
$this->_redirect('*/*/');
return;
}
} else {
$this->_redirect('*/*/');
}
}
}
When overriding core files always the best practice is to minimize the foot print of custom codes.
We shouldn’t be copying the whole function from the core file. Minimum custom foot prints will help us to upgrade Magento easily.
In Acme/ContactExtended/controllers/IndexController.php
you will see that I haven’t followed the best practice I mentioned above.
This is because:
- We have custom fields in the contact form (
ex: First Name, Last Name etc..
)
- We need custom validations
postAction
use $_POST to get posted values in the core
Summary
By following the above method, Magento will process our Controller before Mage_Contact. So you are the master of Contact form now.
Happy coding!