Search code examples
magentoeventsobservers

Magento - Add product programmatically to cart through observer


Here is my questions: What is the right event to hook in for adding a product to quote programmatically (entry sales_flat_quote_item table). Also i have to catch the items/products added to cart from an user/customer, because their data informations will determine the product which will be added programmatically. So the scenario would be:

  1. user/customer adds a product to cart
  2. find the right event for hook in
  3. fetch informations about the products added to cart
  4. add additional product to cart based on a product id and modified its data

In my opinion its better to work with the quote, before the products are written to the database.

I figure out how to add it through Mage_Sales_Model_Quote::_addCatalogProduct(). But i would like to do it through an event observer instead of overwriting core classes.

EDIT

After more research and suggestions here in the post, i was able to get it working. The key thing for me was the understanding of the objects in the observer, their classes and class methods with

var_dump(get_class($quote)); // $item // $product
var_dump(get_class_methods($quote)); // $item // $product

Now knowing the methods are available its easier to figure it out:

Event:

        <events>
        <checkout_cart_product_add_after>
            <observers>
                <unifiedarts_configurablebundleset>
                    <type>singleton</type>
                    <class>Namespace_ConfigurableBundleSet_Model_Observer</class>
                    <method>salesQuoteEditItems</method>
                </unifiedarts_configurablebundleset>
            </observers>
        </checkout_cart_product_add_after>
    </events>

And observer data:

public function salesQuoteEditItems($observer)
{
    $event = $observer->getEvent();
    $item = $event->getQuoteItem();
    $product = $item->getProduct();
    $quote = $item->getQuote();

    $parent = Mage::getModel('catalog/product')->load($product->getParentProductId());

    if($parent->getTypeId() == 'bundle')
    {

        if($product->getTypeId() == 'configurable')
        {

            if ($simpleItem = $item->getOptionByCode('simple_product'))
            {
                // check if the simple product is in the table
                if(!$quote->hasProductId($simpleItem->getProduct()->getId()))
                {
                    echo '<br /><br /> no simple, add it';
                    echo ' simple id '.$simpleItem->getProduct()->getId();

                    $simple = Mage::getModel('catalog/product')->load($simpleItem->getProduct()->getId());
                    $quoteItem = Mage::getModel('sales/quote_item')->setProduct($simple);
                    $parentItem = ( $item->getParentItem() ? $item->getParentItem() : $item );

                    echo 'simple id '.$simpleItem->getProduct()->getId();

                    $item->setRowWeight($product->getWeight());

                    $quoteItem->setQuote($quote);
                    $quoteItem->setQty('1');
                    $quoteItem->setParentItem($parentItem);
                    $quoteItem->setStoreId(Mage::app()->getStore()->getId());
                    $quoteItem->setOriginalCustomPrice(0);

                    $quote->addItem($quoteItem);
                    $quote->save();

                }
                else
                {
                    echo 'simple found change someting'; die;
                }
            }
        }
    }

}

The hole thing is that my extension has to add an configured Item with the bundle. The product view is working. The hard task is to get it in the cart. Now, everything is working fine till going back and add the product again with different (configured) options.

You see above i try to check for the simple product (which i add manually). The code generates two new rows in the sales_flat_quote_item table.

How can i delete the old two entries, or is there a different better approach to set the new data? thanks :)

enter image description here


Solution

  • Declare event observers in config.xml

    <events>
                <checkout_cart_product_add_after>
                    <observers>
                        <custommodule>
                            <class>custommodule/observer</class>
                            <method>cartProductAddAfter</method>
                        </custommodule>
                    </observers>
                </checkout_cart_product_add_after>
                <checkout_cart_product_update_after>
                    <observers>
                        <custommodule>
                            <class>custommodule/observer</class>
                            <method>cartProductUpdateAfter</method>
                        </custommodule>
                    </observers>
                </checkout_cart_product_update_after>
    </events>
    

    Develop the Observers handlers

    class Vendor_Custommodule_Model_Observer 
    {
        /* If you'd like to do the same while updating the shopping cart*/
        public function cartProductUpdateAfter($observer)
        {
            $this->cartProductAddAfter($observer);
        }
    
        public function cartProductAddAfter($observer)
        {
            $product = $observer->getEvent()->getProduct();
            $currentItem = $observer->getEvent()->getQuoteItem();
            $quote = $currentItem->getQuote();
            $quoteItems = $quote->getItems();
    
            /* Detect Product ID and Qty programmatically */
            $idToAdd = "ANY PRODUCT ID";
            $qty = 1;
    
            $productToAdd = Mage::getModel('catalog/product');
            /* @var $productToAdd Mage_Catalog_Model_Product */
            $productToAdd->load($idToAdd);
    
            $this->_addProductToCart($productToAdd, $qty);
        }
    
        protected function _addProductToCart($product, $qty)
        {
            $cart = Mage::getSingleton('checkout/cart');
            /* @var $cart Mage_Checkout_Model_Cart */
            if ($product->getId()) {
                $cart->addProduct($product, $qty);
                return true;
            }
            return false;
        }
    }