nnelson nnelson - 2 months ago 21
PHP Question

Magento: Adding simple products from a bundle to separate lines in the cart

My client is requesting that each simple product within a bundled product they are selling (Clothing Top and Bottom) be added as a separate line item in the cart whenever a user adds it. Can anyone direct me in how to accomplish this? I am fairly good with MVC and the Zend Framework, but I need a bit of help finding the exact files that control adding bundled products to the cart, or an alternate method for getting these items added separately. Please assume that the only possible product type for this clothing is the Bundled product type.

Answer

You will need an observer:

    <checkout_cart_product_add_after>
        <observers>
            <reporting>
                <type>singleton</type>
                <class>Yourcompany_yourmodelname_Model_Observer</class>
                <method>onCartProductAdd</method>
            </reporting>
        </observers>
    </checkout_cart_product_add_after>

Then do the observer:

class ourcompany_yourmodelname_Model_Observer extends Mage_Core_Model_Abstract
{
    /**
     * Binds to the checkout_cart_product_add_after Event and passes control to the helper function to process the quote
     *
     * @param Varien_Event_Observer $observer
     * @return void
     */
    public function onCartProductAdd($observer){
        $product = $observer->getProduct();
        $isProductBundle = ($product->getTypeId() == 'bundle');
        $items_to_add = array();
        $oTypeInstance = $oProduct->getTypeInstance(true);
        $aSelections = $oTypeInstance->getSelectionsCollection($aOptionIds, $product );
        $aOptions = $oTypeInstance->getOptionsByIds($aOptionIds, $product);
        $bundleOptions = $aOptions->appendSelections($aSelections, true);
        foreach ($bundleOptions as $bundleOption) {
            if ($bundleOption->getSelections()) {
                $bundleSelections = $bundleOption->getSelections();    
                foreach ($bundleSelections as $bundleSelection) {
                       $items_to_add[] = $bundleSelection.getID();

               }

            }
       }
       insertExtractedProducts($items_to_add);
    }

     /**
     * Add extracted products into quote
     *
     * @param array $items_to_add
      */
    public function insertExtractedProducts($items_to_add){
        /**@var $cart Mage_Checkout_Model_Cart**/
        $cart = Mage::helper('checkout/cart')->getCart();
        $ids_to_add = array();
        foreach($items_to_add as $item_to_be_added){
            $ids_to_add[] = $item_to_be_added->getProductId();
        }
        $cart->addProductsByIDs($ids_to_add);
        $cart->save();
        Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
        }
   }

Just a simple sample, but it might help.

Bundled products can be complicated to understand, when working with it via code: Here is a sample image: enter image description here

Each Bundled product, have one to many options, which in the end will be links to products to be added to the bundle in the Shopping Cart.

Each Option consists of one to many Selections, which will be the linked products that will end up in the Shopping cart, under this bundled product. One Selection, can typically be set as the default, and will already be selected on the product page. More information can be found at this link on how to create and configure bundled products, because in this document, we will only discuss the programming side of it. The bundled product’s display page, will look like this: enter image description here

It could look like this in the shopping cart, once you clicked on “Add to Cart”: Bundle Sample

Sample Shampoo
1 x Moisturiser-125ml $29.95
Default Conditioner
1 x Moisturiser-60g $99.95

When interrogating this product through code, you load it like any normal product:

$oProduct->load($vProductId);

Once it is loaded, you need to get a product type instance, so that you can load the options for this product type.

$oTypeInstance = $oProduct->getTypeInstance(true);

Now we can get the list of option ID’s for this product in this manner:

$oTypeInstance = $oProduct->getTypeInstance(true);

To interrogate the Selections, we will add the list of options to a collection, then get the Options collection, as well as their respective Selections:

$aSelections = $oTypeInstance->getSelectionsCollection($aOptionIds, $oProduct );
$aOptions = $oTypeInstance->getOptionsByIds($aOptionIds, $oProduct);
$bundleOptions = $aOptions->appendSelections($aSelections, true);

Now we have a Collection of Options, and each Option will have a collection of Selections. We can now loop through the options, and look at their Selctions.

foreach ($bundleOptions as $bundleOption) {
            if ($bundleOption->getSelections()) {
                $bundleSelections = $bundleOption->getSelections();

                foreach ($bundleSelections as $bundleSelection) {
                     // get some data here
                     $vName = $bundleOption->getTitle();
               }

            }
}

To get a list of the Required Selection Products for the Bundled product, you can use the following code:

$requiredChildren = $this->getChildrenIds($product->getId(),$required=true);

You can then loop through the array of ID’s and load the products by their ID’s to get more information regarding those products.

Bundled products in the shopping cart

In order to loop through the selected options of a Bundled product in the shopping card, you can use something like this:

/**
 * @var Mage_Bundle_Model_Product_Type
 */
$typeInstance = $this->getProduct()->getTypeInstance(true);

// get bundle options
$optionsQuoteItemOption =  $this->getItem()->getOptionByCode('bundle_option_ids');
$bundleOptionsIds = unserialize($optionsQuoteItemOption->getValue());
if ($bundleOptionsIds) {
    /**
    * @var Mage_Bundle_Model_Mysql4_Option_Collection
    */
    $optionsCollection = $typeInstance->getOptionsByIds($bundleOptionsIds, $this->getProduct());

    // get and add bundle selections collection
    $selectionsQuoteItemOption = $this->getItem()->getOptionByCode('bundle_selection_ids');

    $selectionsCollection = $typeInstance->getSelectionsByIds(
        unserialize($selectionsQuoteItemOption->getValue()),
        $this->getProduct()
    );

    $bundleOptions = $optionsCollection->appendSelections($selectionsCollection, true);
    foreach ($bundleOptions as $bundleOption) {
        if ($bundleOption->getSelections()) {
            $label = $bundleOption->getTitle()

            $bundleSelections = $bundleOption->getSelections();

            foreach ($bundleSelections as $bundleSelection) {                        
                    $sName = $bundleSelection->getName();
            }
            // some more code here to do stuff
        }
    }
}

This code gets the Options from the Quote Item Bundled Product, and then gets the Options for that product in a collection, and then finds the “Selected” Option Selection.

hth, Shaun