Magento How to update bundle product programmatica

2019-08-10 11:30发布

问题:

I am reading product sku from csv file and my csv file contains bundle product sku. I am traversing through csv data and for each bundle sku I want to add bundle items inside it which I am passing through CSV

Here is the code what I have done

ini_set('auto_detect_line_endings', TRUE);
$magentoPath = getcwd();
require_once ($magentoPath . '/includes/config.php');
require_once ($magentoPath . '/app/Mage.php');
Mage::app();

//read the csv
$bundleCsv = Mage::getBaseDir('var').'/import/bundleImport.csv';
$rows = array_map('str_getcsv', file($bundleCsv));
$header = array_shift($rows);
$csv = array();

foreach ($rows as $row) {
    $csv[] = array_combine($header, $row);
}

Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

echo Mage::app()->getStore()->getId(); exit;

foreach( $csv as $key => $val ){
    if( !isset($val['sku']) || empty($val['sku']) ||  $val['sku'] == '' ){
        echo 'Not Valid Sku';
        continue;
    }

    $_product = Mage::getModel('catalog/product')->loadByAttribute('sku',$val['sku']);

    $opt = $val['bundle_options'];
    $optArr = explode(':', $opt);

    $bundleOptions = array();
    $bundleSelections = array();
    foreach ( $optArr as $key1 => $val1 ) {
        $valTemp = explode( '(', $val1 );
        $title = trim($valTemp[0]);
        $bundleSub[$key1] = array(
                'title' => $title, // option title
                'option_id' => $key1,
                'delete' => '',
                'type' => 'select', // option type
                'required' => '1', // is option required
                'position' => '1'  // option position
        );

        $skuStr = trim($valTemp[1]);
        $skuStrTemp = explode( ')', $skuStr );
        $skuStr = trim($skuStrTemp[0]);

        $skuTemp = explode( '+', $skuStr );

        foreach( $skuTemp as $key2 => $val2 ){
            $product = Mage::getModel('catalog/product');
            $id = Mage::getModel('catalog/product')->getResource()->getIdBySku($val2);

            if( $id ){
                $bundleSelectionsSub[$key2] = array ( // selection ID of the option (first product under this option (option ID) would have ID of 0, second an ID of 1, etc)
                        'product_id' => $id, // if of a product in selection
                        'delete' => '',
                        'selection_price_value' => '10',
                        'selection_price_type' => 0,
                        'selection_qty' => 1,
                        'selection_can_change_qty' => 0,
                        'position' => 0,
                        'is_default' => 1
                );
                $product = null;
            }else{
                continue;
            }
        }
        $bundleSelections[$key1] = $bundleSelectionsSub;
    }

    $bundleOptions = $bundleSub;
    //echo '<pre>'; print_r($bundleOptions); exit;
    try{

        $_product->setCanSaveCustomOptions ( true );
        $_product->setCanSaveBundleSelections ( true );
        $_product->setAffectBundleProductSelections ( true );

        $_product->setBundleOptionsData ( $bundleOptions );
        $_product->setBundleSelectionsData ( $bundleSelections );

        $_product->save();
    }catch ( Exception $e ) {
        Mage::log ( $e->getMessage () );
        echo $e->getMessage ();
    }

    echo 1; exit;
    $_product = null;

}

But this gives me following error as

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`aero_dev`.`catalog_product_bundle_option_value`, CONSTRAINT `FK_CAT_PRD_BNDL_OPT_VAL_OPT_ID_CAT_PRD_BNDL_OPT_OPT_ID` FOREIGN KEY (`option_id`) REFERENCES `catalog_product_bundle_option` (`opt), query was: INSERT INTO `catalog_product_bundle_option_value` (`option_id`, `store_id`, `title`) VALUES (?, ?, ?)

Any help would be appreciated.

回答1:

I could not get it working using above approach so I tried to write custom query to put bundle items in the existing bundle product. When I looked into db I found there are basically 3 tables involved to create bundle items. These are

  • catalog_product_bundle_option
  • catalog_product_bundle_option_value
  • catalog_product_bundle_selection

I went through these tables and tried to looked for what magento puts If I create bundle items from magento admin.

So after some research I have done something like -

foreach( $csv as $key => $val ){
    if( !isset($val['sku']) || empty($val['sku']) ||  $val['sku'] == '' ){
        echo 'Not Valid Sku';
        continue;
    }

    $_product = Mage::getModel('catalog/product')->loadByAttribute('sku',trim($val['sku']));

    $_product->setCanSaveCustomOptions ( true );
    $_product->setCanSaveBundleSelections ( true );
    $_product->setAffectBundleProductSelections ( true );

    $opt = $val['bundle_options'];
    $optArr = explode(':', $opt);

    //get the db write connection
    $connection = Mage::getSingleton('core/resource')->getConnection('core_write');
    $connection->beginTransaction();

    foreach ( $optArr as $key1 => $val1 ) {
        $valTemp = explode( '(', $val1 );
        $title = trim($valTemp[0]);

        //insert into catalog_product_bundle_option with parent product id and type
        $__fields = array();
        $__fields['parent_id'] = $_product->getId();
        $__fields['required'] = 1;
        $__fields['type'] = 'select';
        $__fields['position'] = $key1+1;
        $connection->insert($catalog_product_bundle_option, $__fields);
        $opt_id = $connection->lastInsertId();
        $connection->commit();

        //inert into catalog_product_bundle_option_value with option id, store id, title 
        $__fields = array();
        $__fields['option_id'] = $opt_id;
        $__fields['store_id'] = 0;
        $__fields['title'] = $title;
        $connection->insert($catalog_product_bundle_option_value, $__fields);
        $val_id = $connection->lastInsertId();
        $connection->commit();

        $skuStr = trim($valTemp[1]);
        $skuStrTemp = explode( ')', $skuStr );
        $skuStr = trim($skuStrTemp[0]);

        $skuTemp = explode( '+', $skuStr );
        $pos = 1;
        foreach( $skuTemp as $key2 => $val2 ){
            $id = Mage::getModel('catalog/product')->getResource()->getIdBySku($val2);

            //insert into catalog_product_bundle_selection with option_id, parent product id, product id, position, is_default, selection_price_type, selection_price_value, selection_qty, selection_can_change_qty
            $__fields = array();
            $__fields['option_id'] = $opt_id;
            $__fields['parent_product_id'] = $_product->getId();
            $__fields['product_id'] = $id;
            $__fields['position'] = $pos + 1;
            $__fields['selection_price_type'] = 0;
            $__fields['selection_price_value'] = 10;
            $__fields['selection_qty'] = 1;
            $__fields['selection_can_change_qty'] = 0;
            $connection->insert($catalog_product_bundle_selection, $__fields);
            $connection->commit();
            $pos++;
        }
    }

    //update product
    $_product->save();
    $_product = null;

}

my csv contains 2 columns one is sku and another is bundle options example - sku - 12345678 bundle options - item01(ZIPLOCK18X24+ZIPLOCK16X20):item02(ZIPLOCK14X20+XEROMOCR84208X11)

in which item01 is the option title followed by simple products sku ZIPLOCK18X24, ZIPLOCK16X20 and : seperated incase of multiple options title.

I hope it may help someone.



标签: magento