Magento API: Assigning preexisting simple products to configurable products
Solution 1
Well the notes here helped me get this running. So I thought I'd share with you the code to add a simple product to an existing Configurable Product.
This code assumes the simple product is a valid one to add, I'm not sure what would happen if it wasn't.
private function _attachProductToConfigurable( $_childProduct, $_configurableProduct ) {
$loader = Mage::getResourceModel( 'catalog/product_type_configurable' )->load( $_configurableProduct );
$ids = $_configurableProduct->getTypeInstance()->getUsedProductIds();
$newids = array();
foreach ( $ids as $id ) {
$newids[$id] = 1;
}
$newids[$_childProduct->getId()] = 1;
$loader->saveProducts( $_configurableProduct->getId(), array_keys( $newids ) );
}
Solution 2
The code from the accepted answer by Scimon does not work anymore in recent versions of magento (at least in 1.7). But fortunately, you need just a small fix to get it working again:
private function _attachProductToConfigurable( $_childProduct, $_configurableProduct ) {
$loader = Mage::getResourceModel( 'catalog/product_type_configurable' )->load( $_configurableProduct, $_configurableProduct->getId() );
$ids = $_configurableProduct->getTypeInstance()->getUsedProductIds();
$newids = array();
foreach ( $ids as $id ) {
$newids[$id] = 1;
}
$newids[$_childProduct->getId()] = 1;
//$loader->saveProducts( $_configurableProduct->getid(), array_keys( $newids ) );
$loader->saveProducts( $_configurableProduct, array_keys( $newids ) );
}
Solution 3
I'm working on doing this right now.
So far I've found these items helpful as references:
- http://snippi.net/magento-programmatically-add-configurable-product-color-api
- http://www.omnisubsole.com/blog/2009/07/01/configurable-products-in-magento.html
- http://www.magentocommerce.com/boards/viewthread/6941/P30/
I'll post my code so far, and hopefully update it once it works..
// Set 'item_size' as the super attribute # choose your own attribute!
// this is the 'choose-able' field that differenciates products
$super_attributes=array( Mage::getModel('eav/entity_attribute')
->loadByCode('catalog_product','item_size')
->getData('attribute_id')
);
$product_collection=Mage::getModel('catalog/product')->getCollection();
// Fetch configurable orders
$product_collection->addFieldToFilter('type_id',Array('eq'=>"configurable"));
#$product_collection->addFieldToFilter('sku',Array('eq'=>"ASMCL000002"));
$product_collection->addAttributeToSelect('*');
$count=0;
foreach($product_collection as $product) {
$sku = $product->getSku();
echo "SKU: $sku\n";
$simple_children_collection = Mage::getModel('catalog/product')->getCollection();
$simple_children_collection->addAttributeToSelect('*');
$simple_children_collection->addFieldToFilter('sku',Array('like'=>$sku . "-%"));
echo "children: ";
foreach($simple_children_collection as $child) {
$child_sku = $child->getSku();
echo "$child_sku ";
#visiblity should be 'nowhere'
}
echo "\n";
if (!$product->getTypeInstance()->getUsedProductAttributeIds()) {
# This is a new product without the Configurable Attribue Ids set
$product->getTypeInstance()
->setUsedProductAttributeIds( $super_attributes );
//$product->setConfigurableAttributesData(array($_attributeData));
$product->setCanSaveConfigurableAttributes(true); # Not sure if this is needed.
$product->setConfigurableProductsData(''); # Use this to add child products.
}
$count++;
try {
$product->save();
$productId = $product->getId();
echo $product->getId() . ", $sku updated\n";
}
catch (Exception $e){
echo "$sku not added\n";
echo "exception:$e";
}
}
echo "\nCount is $count\n";
Okay, this uses 'item_size' as the attribute that differentiates the "simple" products. Also, this assumes that the "configurable" parent SKU is the root of the child SKU. For example, ABC001 is the parent while ABC001-SMALL and ABC001-LARGE are the simple children.
Hope that helps someone.
Solution 4
Surprisingly, this works, if all your simple products share the same price:
$childProducts = $configurable->getTypeInstance(true)->getUsedProductIds($configurable);
// Don't add this product if it's already there
if(!in_array($child->getId(), $childProducts)) {
$childProducts[] = $child->getId();
}
$existingIds = $configurable->getTypeInstance(true)->getUsedProductAttributeIds($configurable);
$newAttributes = array();
foreach($configurable->getTypeInstance(true)->getSetAttributes($configurable) as $attribute) {
if(!in_array($attribute->getId(), $existingIds) && $configurable->getTypeInstance(true)->canUseAttribute($attribute)
&& $child->getAttributeText($attribute->getAttributeCode())) {
// Init configurable attribute
$configurableAtt = Mage::getModel('catalog/product_type_configurable_attribute')
->setProductAttribute($attribute);
// Add new attribute to array
$newAttributes[] = array(
'id' => $configurableAtt->getId(),
'label' => $configurableAtt->getLabel(),
'position' => $attribute->getPosition(),
'values' => $configurableAtt->getPrices() ? $configurable->getPrices() : array(),
'attribute_id' => $attribute->getId(),
'attribute_code' => $attribute->getAttributeCode(),
'frontend_label' => $attribute->getFrontend()->getLabel(),
);
}
}
if(!empty($newAttributes)) {
$configurable->setCanSaveConfigurableAttributes(true);
$configurable->setConfigurableAttributesData($newAttributes);
}
$configurable->setConfigurableProductsData(array_flip($childProducts));
$configurable->save();
Solution 5
I this is an un-educated guess, but I think what your asking for can't be done with the existing API. You will have to write your own or just got directly to the DB.
keith
Partner Developer Advocate working in sunny California for sunny Google. "Practice hard, not hardly"
Updated on June 14, 2022Comments
-
keith almost 2 years
I've got a client database with a large range of stock items, which are being uploaded to Magento as simple products.
Now I need to group them up and assign them to configurable products with their size and colour being their configurable attributes.
The Magento API has a Product_Link class, with a promising looking method: catalogue-product-link.assign (link), but I can't for the life of me figure out what arguments I need to make it work with configurable products, providing this is how assign was meant to be used.
-
Devplex almost 15 yearsWith the EAV db schema they use there is no 'just' when directly accessing the DB. The Pain!!!
-
Mensch over 13 yearsI don't know if you're still working on this but I think I've cracked it.
-
Dimitrios Mistriotis over 13 yearsI am trying to do this from a command line script and I fail here: $loader = Mage::getResourceModel( 'catalog/product_type_configurable' )->load( $_configurableProduct ); (first line) Any ideas? I'm currently investigating it and will inform in case of a result.
-
aeno over 11 yearsI updated the code by Scimon to work in recent versions of magento again: see below
-
Mensch about 11 yearsI had an excepted answer? It was a while ago, I've not done any Magento development for a year or so now so go with this.
-
Joseph Leedy about 11 yearsThis probably should have been an edit to the accepted answer IMHO.
-
aeno about 11 years@Joseph: I didn't had enough reputation to do so at the time of writing, so I did post a new answer.