The ecommerce site I’m working on sells some instructional videos, some in different formats (DVD, VHS) and some in mutliple languages (English, Spanish, Portugese, etc). This scenario lends itself to the use of Magento’s Configurable Products. Basically, a configurable product allows the user to choose certain attributes of the product at the time they add the product to their cart. In our scenario, a user would choose the format and the language of the video at the time they add the item to the cart. You can find a good tutorial on setting up Configurable Products through the admin tool at Magento’s Wiki. As described in this wiki entry, you first have to create your custom attributes and then an attribute set that contains the new attributes. I created a Media Format attribute and a Language attribute and then added them to a Videos attribute set. You then create Simple Products based on the attribute set, one for each possbile combination of atttributes, i.e. Video 1 DVD English, Video 1 DVD Spanish, Video 1 VHS English, Video 1 VHS Spanish, etc. Finally you create a configurable product based on the attribute set.
In my case, however, I’m adding products programatically via a php script; not through the admin tool. I traced through the code and the data flow using Firebug on Firefox to determine how configurable products are created. As in the manual process, you first have to create simple products based on the attribute set with all possible combinations of the attributes. Notice that I’m setting the visibility of the simple products to “Nowhere”. This ensures that a user will only see the configurable product.
<?php
define('MAGENTO', realpath('/var/www/magento'));
ini_set('memory_limit', '128M');
require_once MAGENTO . '/app/Mage.php';
Mage::app();
//create dvd english product
$product = Mage::getModel('catalog/product');
$product->setTypeId('simple');
$product->setTaxClassId(0); //none
$product->setWebsiteIds(array(1)); // store id
$product->setAttributeSetId(26); //Videos Attribute Set
/* <option value="6">dvd</option>7
<option value="5">vhs</option> */
$product->setMediaFormat(6); //DVD video
$product->setLanguage(9); //English
$product->setSku(ereg_replace("\n","","videoTest2.1-dvd-english"));
$product->setName(ereg_replace("\n","","videoTest2.1"));
$product->setDescription("videoTest2");
$product->setInDepth("video test");
$product->setPrice("129.95");
$product->setShortDescription(ereg_replace("\n","","videoTest2.1"));
$product->setWeight(0);
$product->setStatus(1); //enabled
$product->setVisibility(1); //nowhere
$product->setMetaDescription(ereg_replace("\n","","videoTest2.1"));
$product->setMetaTitle(ereg_replace("\n","","videotest2"));
$product->setMetaKeywords("video test");
try{
$product->save();
$productId = $product->getId();
echo $product->getId() . ", $price, $itemNum added\n";
}
catch (Exception $e){
echo "$price, $itemNum not added\n";
echo "exception:$e";
}
//create dvd spanish product
$product = Mage::getModel('catalog/product');
$product->setTypeId('simple');
$product->setTaxClassId(0); //none
$product->setWebsiteIds(array(1)); // store id
$product->setAttributeSetId(26); //Videos Attribute Set
/* <option value="6">dvd</option>7
<option value="5">vhs</option> */
$product->setMediaFormat(6); //DVD video
$product->setLanguage(8); //Spanish
$product->setSku(ereg_replace("\n","","videoTest2.1-dvd-spanish"));
$product->setName(ereg_replace("\n","","videoTest2.1"));
$product->setDescription("videoTest2");
$product->setInDepth("video test");
$product->setPrice("129.95");
$product->setShortDescription(ereg_replace("\n","","videoTest2.1"));
$product->setWeight(0);
$product->setStatus(1); //enabled
$product->setVisibility(1); //nowhere
$product->setMetaDescription(ereg_replace("\n","","videoTest2.1"));
$product->setMetaTitle(ereg_replace("\n","","videotest2"));
$product->setMetaKeywords("video test");
try{
$product->save();
$productId = $product->getId();
echo $product->getId() . ", $price, $itemNum added\n";
}
catch (Exception $e){
echo "$price, $itemNum not added\n";
echo "exception:$e";
}
//create vhs english product
$product = Mage::getModel('catalog/product');
$product->setTypeId('simple');
$product->setTaxClassId(0); //none
$product->setWebsiteIds(array(1)); // store id
$product->setAttributeSetId(26); //Videos Attribute Set
/* <option value="6">dvd</option>7
<option value="5">vhs</option> */
$product->setMediaFormat(5); //VHS video
$product->setLanguage(9); //English
$product->setSku(ereg_replace("\n","","videoTest2.1-vhs-english"));
$product->setName(ereg_replace("\n","","videoTest2.1"));
$product->setDescription("videoTest2");
$product->setInDepth("video test");
$product->setPrice("129.95");
$product->setShortDescription(ereg_replace("\n","","videoTest2.1"));
$product->setWeight(0);
$product->setStatus(1); //enabled
$product->setVisibility(1); //nowhere
$product->setMetaDescription(ereg_replace("\n","","videoTest2.1"));
$product->setMetaTitle(ereg_replace("\n","","videotest2"));
$product->setMetaKeywords("video test");
try{
$product->save();
$productId = $product->getId();
echo $product->getId() . ", $price, $itemNum added\n";
}
catch (Exception $e){
echo "$price, $itemNum not added\n";
echo "exception:$e";
}
//create vhs spanish product
$product = Mage::getModel('catalog/product');
$product->setTypeId('simple');
$product->setTaxClassId(0); //none
$product->setWebsiteIds(array(1)); // store id
$product->setAttributeSetId(26); //Videos Attribute Set
/* <option value="6">dvd</option>7
<option value="5">vhs</option> */
$product->setMediaFormat(5); //DVD video
$product->setLanguage(8); //Spanish
$product->setSku(ereg_replace("\n","","videoTest2.1-vhs-spanish"));
$product->setName(ereg_replace("\n","","videoTest2.1"));
$product->setDescription("videoTest2");
$product->setInDepth("video test");
$product->setPrice("129.95");
$product->setShortDescription(ereg_replace("\n","","videoTest2.1"));
$product->setWeight(0);
$product->setStatus(1); //enabled
$product->setVisibility(1); //nowhere
$product->setMetaDescription(ereg_replace("\n","","videoTest2.1"));
$product->setMetaTitle(ereg_replace("\n","","videotest2"));
$product->setMetaKeywords("video test");
try{
$product->save();
$productId = $product->getId();
echo $product->getId() . ", $price, $itemNum added\n";
}
catch (Exception $e){
echo "$price, $itemNum not added\n";
echo "exception:$e";
}
?>
Once you’ve created each of the simple products, you can create the Configurable Product. Configruable Products have two special variables that you must set: Configurable Products Data and Configurable Attributes Data. Configurable Products Data is an array containing the simple products, along with their configurable attribute data and pricing information, that are associated with the configurable product. The JSON “object” that is passed via the admin interface looks like:
{"5792": [{"label": "dvd", "attribute_id": "491", "value_index": "6", "is_percent": 0, "pricing_value"
: ""}, {"label": "Endlish", "attribute_id": "500", "value_index": "9", "is_percent": 0, "pricing_value"
: ""}], "5807": [{"label": "dvd", "attribute_id": "491", "value_index": "6"}, {"label": "Spanish", "attribute_id"
: "500", "value_index": "8", "is_percent": 0, "pricing_value": ""}], "5791": [{"label": "vhs", "attribute_id"
: "491", "value_index": "5", "is_percent": 0, "pricing_value": ""}, {"label": "Endlish", "attribute_id"
: "500", "value_index": "9"}], "5808": [{"label": "vhs", "attribute_id": "491", "value_index": "5"},
{"label": "Spanish", "attribute_id": "500", "value_index": "8"}]}
which translates to this in PHP:
$data = array(
'5791'=>array('0'=>
array('attribute_id'=>'491','label'=>'vhs','value_index'=>'5','is_percent'=>0,'pricing_value'=>''),
'1'=>
array('attribute_id'=>'500','label'=>'English','value_index'=>'9','is_percent'=>0,'pricing_value'=>'')
),
'5792'=>array('0'=>
array('attribute_id'=>'491','label'=>'dvd','value_index'=>'6','is_percent'=>0,'pricing_value'=>''),
'1'=>
array('attribute_id'=>'500','label'=>'English','value_index'=>'9','is_percent'=>0,'pricing_value'=>'')
),
'5807'=>array('0'=>
array('attribute_id'=>'491','label'=>'dvd','value_index'=>'6','is_percent'=>0,'pricing_value'=>''),
'1'=>
array('attribute_id'=>'500','label'=>'Spanish','value_index'=>'8','is_percent'=>0,'pricing_value'=>'')
),
'5808'=>array('0'=>
array('attribute_id'=>'491','label'=>'vhs','value_index'=>'6','is_percent'=>0,'pricing_value'=>''),
'1'=>
array('attribute_id'=>'500','label'=>'Spanish','value_index'=>'8','is_percent'=>0,'pricing_value'=>'')
)
);
The is_percent and pricing_value options allow you to set different prices for each customization. So if you wanted the DVD’s to cost $5 more than the default, just set the pricing_value to 5. Or if you prefer to do a percent of the default cost, set the is_percent parameter to 1 and enter a percent (0 to 100) for the pricing_value.
The Configurable Attributes Data is another array that defines which of the product attributes are configurable. It takes this form:
$data = array('0'=>array('id'=>NULL,'label'=>'Media Format','position'=> NULL,
'values'=>array('0'=>
array('value_index'=>5,'label'=>'vhs','is_percent'=>0,
'pricing_value'=>'0','attribute_id'=>'491'),
'1'=>
array('value_index'=>6,'label'=>'dvd',
'is_percent'=>0,'pricing_value'=>'0','attribute_id'=>'491')
),
'attribute_id'=>491,'attribute_code'=>'media_format','frontend_label'=>'Media Format',
'html_id'=>'config_super_product__attribute_0'),
'1'=>array('id'=>NULL,'label'=>'Language','position'=> NULL,
'values'=>array('0'=>
array('value_index'=>8,'label'=>'Spanish','is_percent'=>0,
'pricing_value'=>'0','attribute_id'=>'500'),
'1'=>
array('value_index'=>9,'label'=>'English',
'is_percent'=>0,'pricing_value'=>'0','attribute_id'=>'500')
),
'attribute_id'=>500,'attribute_code'=>'media_format','frontend_label'=>'Language',
'html_id'=>'config_super_product__attribute_1')
);
Putting it all together:
<?php
define('MAGENTO', realpath('/var/www/magento'));
ini_set('memory_limit', '128M');
require_once MAGENTO . '/app/Mage.php';
Mage::app();
//create dvd english product
$product = Mage::getModel('catalog/product');
$product->setTypeId('configurable');
$product->setTaxClassId(0); //none
$product->setWebsiteIds(array(1)); // store id
$product->setAttributeSetId(26); //Videos Attribute Set
$product->setSku(ereg_replace("\n","","videoTest2.2"));
$product->setName(ereg_replace("\n","","videoTest2.2"));
$product->setDescription("videoTest2.2");
$product->setInDepth("video test");
$product->setPrice("129.95");
$product->setShortDescription(ereg_replace("\n","","videoTest2.2"));
$product->setWeight(0);
$product->setStatus(1); //enabled
$product->setVisibility(4); //catalog and search
$product->setMetaDescription(ereg_replace("\n","","videoTest2.2"));
$product->setMetaTitle(ereg_replace("\n","","videotest2.2"));
$product->setMetaKeywords("video test");
$data = array('5791'=>
array('0'=>
array('attribute_id'=>'491','label'=>'vhs','value_index'=>'5','is_percent'=>0,'pricing_value'=>''),
'1'=>
array('attribute_id'=>'500','label'=>'English','value_index'=>'9','is_percent'=>0,'pricing_value'=>'')
),
'5792'=>array('0'=>
array('attribute_id'=>'491','label'=>'dvd','value_index'=>'6','is_percent'=>0,'pricing_value'=>''),
'1'=>
array('attribute_id'=>'500','label'=>'English','value_index'=>'9','is_percent'=>0,'pricing_value'=>'')
),
'5807'=>array('0'=>
array('attribute_id'=>'491','label'=>'dvd','value_index'=>'6','is_percent'=>0,'pricing_value'=>''),
'1'=>
array('attribute_id'=>'500','label'=>'Spanish','value_index'=>'8','is_percent'=>0,'pricing_value'=>'')
),
'5808'=>array('0'=>
array('attribute_id'=>'491','label'=>'vhs','value_index'=>'6','is_percent'=>0,'pricing_value'=>''),
'1'=>
array('attribute_id'=>'500','label'=>'Spanish','value_index'=>'8','is_percent'=>0,'pricing_value'=>'')
)
);
$product->setConfigurableProductsData($data);
$data = array('0'=>array('id'=>NULL,'label'=>'Media Format','position'=> NULL,
'values'=>array('0'=>
array('value_index'=>5,'label'=>'vhs','is_percent'=>0,
'pricing_value'=>'0','attribute_id'=>'491'),
'1'=>
array('value_index'=>6,'label'=>'dvd',
'is_percent'=>0,'pricing_value'=>'0','attribute_id'=>'491')
),
'attribute_id'=>491,'attribute_code'=>'media_format','frontend_label'=>'Media Format',
'html_id'=>'config_super_product__attribute_0'),
'1'=>array('id'=>NULL,'label'=>'Language','position'=> NULL,
'values'=>array('0'=>
array('value_index'=>8,'label'=>'Spanish','is_percent'=>0,
'pricing_value'=>'0','attribute_id'=>'500'),
'1'=>
array('value_index'=>9,'label'=>'English',
'is_percent'=>0,'pricing_value'=>'0','attribute_id'=>'500')
),
'attribute_id'=>500,'attribute_code'=>'media_format','frontend_label'=>'Language',
'html_id'=>'config_super_product__attribute_1')
);
$product->setConfigurableAttributesData($data);
$product->setCanSaveConfigurableAttributes(1);
try{
$product->save();
$productId = $product->getId();
echo $product->getId() . ", $price, $itemNum added\n";
}
catch (Exception $e){
echo "$price, $itemNum not added\n";
echo "exception:$e";
}
?>
I came up with my attribute_ids, values, etc by viewing the source of the admin interface. I’m sure there’s a way to use the attribute model to get the values but since I manually create the attributes and attribute sets, I haven’t bothered.