创建可配置的产品Configurable Product

接着上篇文章写点技术性文章,再次充实下Magento让人汗颜的开发文档。这次我要创建的是Configurable Product。创建该类型的产品是相当的复杂。首先必须创建一个全局Global的属性,类型为Drodown,设置Ues To Create Configurable这Product 为 Yes。这样新建一个Configurable Product 的时候选择这个属性就可以了。建议新建一个单独的Attribute Set,例如Configurable,把需要配置的属性,例如size加入到这个Configurable的属性组。 然后创建独立的simple类型的产品,设置size这个属性值,即可与Configurable Product 建立关联。下面这段代码就是建立产品之间的联系。

前期准备

创建一个全局Global的size属性,设置类型为Dropdown,设置Use to设置为Yes。设置size的值为S、M、L。创建一个属性集Attribute Set为Configurable,添加size属性到该属性集。

$attribute = array(
    // 定义Size基本属性
    'value' => array(
        'label'      => 'Size',
        'attribute_code' => 'size',
        'frontend_label' => 'Size',
        'store_label'    => 'Size',
    ),
    //定义size的3种大小
    'size' => array(
        '0' => 'S',
        '1' => 'M',
        '2' => 'L', 
    ),
    //定义size属性的attribute id
    'id' => array(
        'size' => '128'
    ),
    //定义size的3个option的index value
    'options' => array(
        'size' => array(
            'S' => '3',
            'M' => '4',
            'L' => '5',
        ),
    ),
    //定义size属性的3种价钱
    'price' => array(
        'size' => array(
            'S' => '10',
            'M' => '20',
            'L' => '30',
        )
    )
);

属性与产品进行关联

创建Configurable Product

$data = array(
    'qty' => '999',
    'sku' => 'configurable',
    'price' => '0',
    'weight' => '100',
    'status' => 'Enabled',
    'is_in_sock' => '1',
    'name' => 'Configurable Product',
    'description' => 'Configurable Product',
    'visibility' => 'Catalog, Search',
    'attribute_set' => 'Default',
    'type' => 'configurable',
    'website' => 'base',
);
$model = Mage::getModel('catalog/convert_adapter_product');
$model->saveRow($data);
$configProductId = $model->getProductModel->getId();
$sku = $data['sku'];
$name = $data['name'];

创建3个simple Product,因为size的值有3个。并创建与Configruable Product 属性关联的数组$configurable_products_data

$attributeData = array();
$configAttributeData = array();
$configurable_products_data = array();
//default stre id is 1
$storeId = 1;
for($i = 0;$i < 3;$i++){
    $data['type'] = 'simple';
    $data['name'] = $name.'-'.$i;
    $data['sku']  = $sku.'-'.$i;
    $data['visibility']= 'Not Visible Individually';
    $data['price'] = '100';//price = configproduct price +simple product price
    $model->saveRow($data);
    //get simple product id 
    $productId = $model->getProductModel()->getId();
    // THE POINT: update the super attribute ,Magento call it super attribute
    //注意这里关联Configurable的绝招:设置产品的Size属性
    $attributeData['size'] = $attribute['size'][$i];
    Mage::getSingleton('catalog/product_action')->updateAttributes(array($productId), $attributeData, $storeId);
    //构造产品关联数组
    $configAttributeData = array(
                    'label'     => $attributeData['size'],
                    'attribute_id'  => $attribute['id']['size'],
                    'value_index'   => $attribute['options']['size'][$attributeData['size']],
                    'is_percent'    => '0',
                    'pricing_value' => $attribute['price']['size'][$attributeData['size']],
                );
    $configurable_products_data[$productId][] = $configAttributeData;
}

Configurable Product关联Size属性

$configurable_attributes_data = array();
$configurable_attributes_data[] = array(
    'id'        =>  null,
        'label'     =>  $attribute['value']['label'],
        'use_default'   =>  null,
        'position'  =>  null,
        'values'    =>  array(),
        'attribute_id'  =>  $this->_importAttribute['value'][$key],
        'attribute_code'=>  $attribute['value']['attrinbute_code'],
        'frontend_label'=>  $attribute['value']['frontend_label'],
        'store_label'   =>  $attribute['value']['store_label'],
        'html_id'   =>  'configurable__attribute_0',
);
$product = Mage::getModel('catalog/product');
$product = $product->load($configProductId);
$superAttribteIds = array();
// set product super attribute
//再次发个大招:Configurable Product 关联Size属性
foreach ($configurable_attributes_data as $attributeData) {
                $id = isset($attributeData['id']) ? $attributeData['id'] : null;
                $model = Mage::getModel('catalog/product_type_configurable_attribute')
                   ->setData($attributeData)
                   ->setId($id)
                   ->setStoreId($product->getStoreId())
                   ->setProductId($product->getId())
                   ->save();
                $superAttribteIds[$attributeData['label']] = $model->getId();
        }
//设置关联属性的id
//set super attribute id of config attribute data
foreach ($configurable_attributes_data as $k => $v){
        if($value = $superAttribteIds[$v['label']]){
            $configurable_attributes_data[$k]['id'] = $value;
        }
}

构造simple 和Confinurable Product的关联数组

“`
//构造出来的数组大致是这个样子的
//$configurable_products_data
array(
'2' => array(
array(
'label' => 'Size',
'attribute_id' => '128',
'value_index' => '3',
'is_percent' => '0',
'pricing_value' => '10',
)
),
'3' => array(
array(
'label' => 'Size',
'attribute_id' => '128',
'value_index' => '4',
'is_percent' => '0',
'pricing_value' => '20',
)
),
'4' => array(
array(
'label' => 'Size',
'attribute_id' => '128',
'value_index' => '5',
'is_percent' => '0',
'pricing_value' => '30',
)
)
)

//$configurable_attributes_data
array (
array (
'id' => '1',
'label' => 'Size',
'use_default' => NULL,
'position' => NULL,
'values' =>
array (
array (
'label' => 'Size',
'attribute_id' => '128',
'value_index' => '3',
'is_percent' => '0',
'pricing_value' => '10.0000',
),
array (
'label' => 'Size',
'attribute_id' => '128',
'value_index' => '4',
'is_percent' => '0',
'pricing_value' => '20.0000',
),
array (
'label' => 'Size',
'attribute_id' => '128',
'value_index' => '5',
'is_percent' => '0',
'pricing_value' => '30.0000',
),
),
'attribute_id' => '128',
'attribute_code' => 'size',
'frontend_label' => 'Size',
'store_label' => 'Size',
'html_id' => 'configurable__attribute_0',
),
)

//refer app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
//line 91
$product->setConfigurableProductsData($configurable_products_data);
$product->setConfigurableAttributesData($configurable_attributes_data);
$product->setCanSaveConfigurableAttributes(1);
try{
$product->save();
//return $product->getId();
}
catch (Exception $e){
echo Mage::helper('core')->__('Configurable Product ID %s CAN NOT be saved because of %s', $configProductId , $e->getMessage()));
}“`

参考资料

  1. Bulk Update Product Attribute
  2. Configurable Products in Magento
  3. 使用Magento Api创建configurable product

创建Attribute 和 Attribute Set

自从上次总结后,俺是忙得团团转,忙着找工作,忙着打代码,忙着忙着,一晃一个月就过去了。清明放假除了祭奠亲人外,顺便总结下最近的成果。最近一直在忙的项目是数据导入。从在我看来后台"很原始"的Zencart 平台迁移到扩展性强,性能很弱的Magentlo上。在迁移数据的过程中,遇到了需要创建Attibute Set的问题,在这里记录下我的解决方案。btw,在我看来,Mqgento的开发文挡匮乏得令人发指的程度,还有这么多优秀插件出现,这不得不得让人相信这是个奇迹!好了,废话不多说,上代码儿。

获取默认的Attribute Set 和Gourp Id

setType('catalog_product')->getTypeId();
//get default type id
//$entityTypeId = Mage::getModel('catalog/product')->getResource()->getTypeId();

//get Default Attribute Set id
$defaultAttributeSetID = Mage::getModel('eav/entity_attribute_set')->getCollection()
->setEntityTypeFilter($entityTypeId)
->addFiledToFilter('attribute_set_name','Default')
->getFirstItem()
->getAttributeSetId();
?>

创建自定义的Attribute Set

//create Attribute Set Name: Configurable;
//refer app/code/core/Mage/Adminhtml/controllers/Catalog/Product/SetController.php 
// line 142
$model = Mage::getModel('eav/entity_attribute_set');
$entityTypeID = Mage::getModel('catalog/product')->getResource()->getTypeId();
$model->setEntityTypeId($entityTypeID);
$model->setAttributeSetName('Configurable');
$model->validate();
$model->save();
$model->initFromSkeleton($defaultAttributeSetID);
$model->save();

//get the Create Attribute Set ID and Group ID
$attributeSet = array();
$attributeSet['id'] = $model->getId();
$attributeSet['group_id'] = $model->load($attributeSet['id'])->getDeafultGroupId();
</pre>

### 创建自定义属性

<pre lang="php">//create attribute function
// refer app/code/core/Mage/Adminhtml/controllers/Ctalog/Product/AttribteController.php
// line 186
function createAttribute($code, $label, $attribute_type, $product_type , 
$deafultValue = array() , $attributeSet , $isRequired = '0' , $isConfigurable = 1){
        $data = array(
            'attribute_code' => $code,
            'is_global' => '1',
            'frontend_input' => $attribute_type,
            'default_value_text' => '',
            'default_value_yesno' => '0',
            'default_value_date' => '',
            'default_value_textarea' => '',
            'is_unique' => '0',
            'is_required' => $isRequired,
            'apply_to' => array($product_type),
            'is_configurable' => $isConfigurable,
            'is_searchable' => '0',
            'is_visible_in_advanced_search' => '0',
            'is_comparable' => '0',
            'is_used_for_price_rules' => '0',
            'is_wysiwyg_enabled' => '0',
            'is_html_allowed_on_front' => '1',
            'is_visible_on_front' => '0',
            'used_in_product_listing' => '0',
            'used_for_sort_by' => '0',
            'frontend_label' => array($label)
        );

        $model = Mage::getModel('catalog/resource_eav_attribute');

        if (!isset($data['is_configurable'])) {
            $data['is_configurable'] = 0;
        }
        if (!isset($data['is_filterable'])) {
            $data['is_filterable'] = 0;
        }
        if (!isset($data['is_filterable_in_search'])) {
            $data['is_filterable_in_search'] = 0;
        }

        if (is_null($model->getIsUserDefined()) || $model->getIsUserDefined() != 0) {
            $data['backend_type'] = 
            $model->getBackendTypeByInput($data['frontend_input']);
        }

        $data['option']['value'] = $deafultValue;

        $model->addData($data);
    $typeId = Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId();
        $model->setEntityTypeId($typeId);
        $model->setIsUserDefined(1);
    if($attributeSet && isset($attributeSet['id']) && isset($attributeSet['group_id'])){
            //set attibute to the Attribute Set
        $model->setAttributeSetId($attributeSet['id']);
            $model->setAttributeGroupId($attributeSet['group_id']);
    }

        try {
            $model->save();
            return $model->getId();
        }
        catch (Exception $e) { 
            echo '

Sorry, error occured while trying to save the attribute. Error: '.$e->getMessage().'

';
        }
    }
// create select attribute
createAttribute('xbc_select','Xbc Select','select','simple');
//create text attribute
createAttribute('xbc_text','Xbc Text','text','grouped');
//create boolean attribute
createAttribute('xbc_bool','Xbc Bool','bollean','');
?>

以上代码在Magento Community 1.6.2测试通过

参考资料

  1. Programatically create attribute in Magento, useful for the “on the fly” import system

  2. Programmatically Adding Attributes and Attribute Sets

  3. Playing with Attribute Set in Magento