Creation of configurable products for developers
A configurable product creation is pretty similar to a usual product creation, with a few additional steps required.
A simple product can be created in this way:
$pr = Mage::getModel('catalog/product'); $pr->setAttributeSetId($att_id); $pr->setSku($variantcode); $pr->setTypeId('simple'); $pr->setName('Simple product name'); $pr->setDescription('Simple product desciption'); $pr->setShortDescription('Simple product short description'); $pr->setCreatedAt(strtotime('now')); $pr->setStatus(1); $pr->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH); $pr->setWebsiteIDs(array(1)); $pr->setStockData(array( 'is_in_stock' => 1, 'qty' => 99999 )); $pr->setTaxClassId(0); $pr->setCategoryIds($mpr->getCategoryIds()); $pr->save();
The att_id in the code above should be set to the right attribute_id of the “attribute set”. For example if an attribute set url is the following:
/admin/catalog_product_set/edit/id/26/key/22cd8ab71f9c0064f57767e9bf4a7363/
then the attribute id is 26 in this case. Of course it's possible to receive the attribute id by the attribute name.
Also it's required to set up required attributes for a simple product. In my case it was size and color. So I've set them up in this way (before I saved the product):
$pr->setData('size', $att_sizes[$size['option_name']]); $pr->setData('color', $att_colors[$color['option_name']]); $pr->save();
When one or several simple products are created, we are able to create the configurable product. The first steps are the same, the difference is only in the type id:
$mpr = Mage::getModel('catalog/product'); ... $pr->setTypeId('configurable'); ... $mpr->setConfigurableProductsData($all_child_products); $mpr->setConfigurableAttributesData(array( array_merge($att_size->getData(), array('label' => '', 'values' => $size_values)), array_merge($att_color->getData(), array('label' => '', 'values' => $color_values)) )); $mpr->setCanSaveConfigurableAttributes(true); $mpr->save();
Here is the explanation of the required data. The setConfigurableProductsData function saves the set of child products. The required param should be given in the following format:
array( child_product_id => array( array( array('attribute_id' => '<attribute # here>', 'label' => '<label here>', 'value_index' => '<option # here>', 'pricing_value' => 0, 'is_percent' => 0), ) ), // next child product here.
For the setConfigurableAttributesData function, the simple getData() can be used from the attribute object. The situation with “values” is not so easy - it should be an array of the child products attributes:
$values = array( array('attribute_id' => '<attribute # here>', 'label' => '<label here>', 'value_index' => '<option # here>', 'pricing_value' => 0, 'is_percent' => 0), # attribute 2 here )
Example of usage
It would be easier to understand how the code works using a working live example. This example is a part of a modification that imports products with variants from X-Cart into Magento.
Below are only the parts that help to understand a mechanism of configurable product creation in Magento.
# we are receiving the size and the color attributes here, and it's options # as the separate array $att_size = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product','size'); $att_sizes = $this->__getAttList('size'); $att_color = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product','color'); $att_colors = $this->__getAttList('color'); $mpr = <creation of the configurable product as in the example above>; $sizes = <get the sizes array from import file>; $colors = <get the colors array from import file>; $size_values = $color_values = $all_child_products = array(); foreach($sizes as $size) foreach($colors as $color) { $variantcode = $productcode.'_'.$color['option_code'].'_'.$size['option_name']; $pr = <creation of the child product here>; # we have to create the new option in the attribute and re-create # our cache array if there are no appropriate option in the cache if (!isset($att_sizes[$size['option_name']])) $att_sizes = $this->__addAtt($att_size->getId(), 'size', $size['option_name']); if (!isset($att_colors[$color['option_name']])) $att_colors = $this->__addAtt($att_color->getId(), 'color', $color['option_name']); # preparing of the sub-products array $all_child_products[$pr->getId()] = array( $sv = array('attribute_id' => $att_size->getData('attribute_id'), 'label' => $size['option_name'], 'value_index' => $att_sizes[$size['option_name']], 'pricing_value' => 0, 'is_percent' => 0), $cv = array('attribute_id' => $att_color->getData('attribute_id'), 'label' => $color['option_name'], 'value_index' => $att_colors[$color['option_name']], 'pricing_value' => 0, 'is_percent' => 0), ); # and in the save time we are preparing the arrays for the # configurable product values. $size_values[] = $sv; $color_values[] = $cv; # we are set the color and size for the child product, # and we have make it by attribute id $pr->setData('size', $att_sizes[$size['option_name']]); $pr->setData('color', $att_colors[$color['option_name']]); $pr->save(); } # special configuration actions $mpr->setConfigurableProductsData($all_child_products); $mpr->setConfigurableAttributesData($tmp = array( array_merge($att_size->getData(), array('label' => '', 'values' => $size_values)), array_merge($att_color->getData(), array('label' => '', 'values' => $color_values)) )); $mpr->setCanSaveConfigurableAttributes(true); $mpr->save();
Some of the additional function from the example above:
# with this function we are able to add the new option value to the "size" or # "color" attribute private function __addAtt($att_id, $opt, $value) { $option['attribute_id'] = $att_id; $option['value']['any_key_that_resolves_to_zero'][0] = $value; $setup = new Mage_Eav_Model_Entity_Setup('core_setup'); $setup->addAttributeOption($option); return $this->__getAttList($opt); } # with this function we are simply receiving the short cache array # it is done to simplify the work private function __getAttList($option) { $attributes = Mage::getResourceModel('eav/entity_attribute_collection') ->addFieldToFilter('attribute_code', $option) ->load(false); $attribute = $attributes->getFirstItem(); $attribute->setSourceModel('eav/entity_attribute_source_table'); $atts = $attribute->getSource()->getAllOptions(false); $result = array(); foreach($atts as $tmp) $result[$tmp['label']] = $tmp['value']; return $result; }