Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending Magento Shopping Cart

I need to extend the Magento shopping cart to include an extra step for a store locator. I understand that I need to overwrite the core OnePage controller (Mage_Checkout_OnepageController) and blocks (Mage_Checkout_Block_Onepage) but what needs to be done with regards to keeping track of the extra information (e.g. user's selected options from my custom step).

like image 213
Lyndon Hook Avatar asked Jun 19 '12 00:06

Lyndon Hook


1 Answers

There are a number of steps required here to get the whole solution.

Firstly, create a new module. Use the ModuleCreator if you wish.

Then, write a setup script in your module to add the new fields to Magento's attribute structure, e.g. :

 $setup = new Mage_Sales_Model_Mysql4_Setup('core_setup');
 $setup->startSetup();

 $setup->addAttribute('quote', 'my_attribute', array('type' => 'varchar', 'visible' => false, 'required' => false));
 $setup->addAttribute('order', 'my_attribute', array('type' => 'varchar', 'visible' => false, 'required' => false));
 $setup->addAttribute('invoice', 'my_attribute', array('type' => 'varchar', 'visible' => false, 'required' => false));
$setup->addAttribute('creditmemo', 'my_attribute', array('type' => 'varchar', 'visible' => false, 'required' => false));

Note the use of the Mage_Sales_Model_Mysql4_Setup to add the fields to the relevant sales_flat_quote and sales_flat_order tables.

Now, insert the following values in your module's config.xml file:

<global>

    <fieldsets>
        <sales_convert_quote>
            <my_attribute>
                <to_order>*</to_order>
            </my_attribute>
        </sales_convert_quote>
        <sales_convert_order>
            <my_attribute>
                <to_cm>*</to_cm>
                <to_invoice>*</to_invoice>
            </my_attribute>
        </sales_convert_order>
    </fieldsets>

That will instruct Magento to copy the values of your custom field from quote to order to invoice and credit_memo, etc.

Then in your custom block/controller code, you will be able to use Magento's magic getters and setters to persist the values.

$oQuote = Mage::getSingleton('checkout/session')->getQuote();
$oQuote->setMyAttribute('some_value');
$oQuote->save();

You should see the new column and value saved in sales_flat_quote. Then once the customer completes checkout, the same value should be saved in sales_flat_order.

Note that the above code can be extended to work for quote_item and order_item by just changing quote to quote_item etc, however, if you wish to save attribute values that have been set on your products, then some extra work is required.

Insert a new block of XML into your config.xml (again inside the global node):

   <sales>
        <quote>
            <item>
                <product_attributes>
                    <my_attribute />
                </product_attributes>
            </item>
        </quote>
    </sales>

Where my_attribute is the attribute code on the product model. That will make the my_attribute available on the linked product, so you can access it via

$oQuoteItem->getProduct()->getMyAttribute()

without needing to perform a full Mage::getModel('catalog/product')->load($oQuoteItem->getProductId()). This is much more efficient.

Then, you will need an observer to copy the values from the product object to the quote_item object. So, declare your observer in the config.xml:

    <events>
        <sales_quote_item_set_product>
            <observers>
                <quoteitem_set_custom_data>
                    <type>singleton</type>
                    <class>mymodule/observer</class>
                    <method>setCustomDataOnQuoteItem</method>
                </quoteitem_set_custom_data>
            </observers>
        </sales_quote_item_set_product>
    <events>

and write code in your observer class like this:

public function setCustomDataOnQuoteItem($oObserver){
    $oProduct = $oObserver->getProduct();
    $oQuoteItem = $oObserver->getQuoteItem();
    foreach(array('my_attribute') as $vAttributeCode){
        $oQuoteItem->setData($vAttributeCode,$oProduct->getData($vAttributeCode));
    }
}
like image 195
Jonathan Day Avatar answered Oct 24 '22 19:10

Jonathan Day