以编程方式创建的可配置项不显示选项,直到我手动将其保存在管理面板中


Programmatically created configurable item doesn't show options until I manually save it in the admin panel

我正在代码中创建一个可配置的产品(我正在做一个导入模块),一切看起来都很好。添加了属性,简单的库存项目被添加到可配置的产品中,没有任何问题,但是,当我在字体端查看项目时,它显示为一个简单的产品(没有选项),但是当我在管理面板中保存打开并保存产品时,它会正确显示前端的选项。

我在重新保存项目之前和之后使用以下代码来检查是否有任何属性不匹配(假设我错过了一些东西)

foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $code=>$attribute)    
{
    $val = Mage::getResourceModel('catalog/product')->getAttributeRawValue($product->getId(), $code, $storeId);
    Mage::log($code . '=>' . $val);
}

新导入的产品(不显示选项)和手动保存的产品(显示选项)之间的所有值都匹配。

以下是我用来创建产品的代码(我省略了将属性/简单项目添加到可配置产品的位,但请告诉我是否需要):

$productData = array(
    'name'              => $name,
    'websites'          => array(1, 2), 
    'short_description' => $shortDescription,
    'description'       => $longDesc,
    'status'            => 1,
    'weight'            => $weight,
    'tax_class_id'      => 2, //0:None;2:Taxable Goods;4:Shipping
    'categories'        => $categoryIds,
    'price'             => $sellPrice,
);
if ($parentStockItem == null) // != null is child item, == false is simple item,  == null is config item
{
    $productData['has_options'] = 1;
    $productData['required_options'] = 1;
    $productData['msrp_enabled'] = 2; //added to test as this was missing in my comparison check
    $productData['msrp_display_actual_price_type'] = 4;  //added to test as this was missing in my comparison check
}
return $mc->create($type, $setId, $stockCode, $productData);

我是否需要做一些事情来设置一个项目来显示前端的选项?

好的,我通过比较保存项目之前和之后的数据库快照之间的数据来找到问题。

发生这种情况的原因是cataloginventory_stock_status中的stock_status标志。此值默认为0,但当您保存产品时,它将其设置为1。您还需要确保您正在设置其他库存选项,因此将以下内容添加到我的例程中可以解决此问题:

$stockItem = Mage::getModel('cataloginventory/stock_item');
$stockItem->assignProduct($product);
$stockItem->setData('stock_id', 1);
$stockItem->setData('qty', 0);
$stockItem->setData('use_config_min_qty', 1);
$stockItem->setData('use_config_backorders', 1);
$stockItem->setData('min_sale_qty', 1);
$stockItem->setData('use_config_min_sale_qty', 1);
$stockItem->setData('use_config_max_sale_qty', 1);
$stockItem->setData('is_in_stock', 1);
$stockItem->setData('use_config_notify_stock_qty', 1);
$stockItem->setData('manage_stock', 1);
$stockItem->save();
//This section is what was required.
$stockStatus = Mage::getModel('cataloginventory/stock_status');
$stockStatus->assignProduct($product);
$stockStatus->saveProductStatus($product->getId(), 1);

项目现在在导入后直接显示正确的选项。

我遇到了同样的问题。这是个棘手的问题。我的解决方案可能不太优雅,但它已经运行了一年,没有任何问题。虽然有点丑,但是很好用。

是的,你需要做很多具体的事情。我将只发布我编写的接受主产品及其相关产品的源代码,而不是解释每件事。归根结底,你必须首先创建一个简单的产品,将其用作可配置产品的"模板"。

您必须首先创建主产品和相关产品,然后使用下面的代码创建可配置产品。如果在创建可配置产品后不希望主产品存在,只需添加代码将其删除,然后将新可配置产品的entity_id上的sku更改为主产品的sku。

确保您将YOUR_MAGENTO_DBNAME更改为您的数据库名称

public function createConfigurableProduct($master_sku, $sku_list) {
    // Recreate the array from the serialized string
    try {
        $sku = array();
        $sku = explode(",", $sku_list);
        if (empty($sku)) {
            die ("You have to pass a valid SKU list");
        }
        // Set an object up for the master sku passed by soap
        $masterProduct = Mage::getModel('catalog/product')->loadByAttribute('sku', $master_sku);
        $attrib = $this->getAttribFromProdId($masterProduct->entity_id);
        if ($attrib->attribute_set_id == "") {
            die ("Could not get master product attribute set id from master product");
        }
        $categories = $masterProduct->getResource()->getCategoryIds($masterProduct); 
        if (empty($categories)) {
            die ("could not get the categories that the master product is in. This code requires it is in at least one category");
        }
        // Create the configurable product based on the master product sku passed through SOAP
        $newProductObj = Mage::getResourceModel('catalog/product_collection')->getData();
        $attributes = $masterProduct->getAttributes();
        // Set attributes
        $product = Mage::getModel('catalog/product');
        // Create master copy
        foreach ($attributes as $attr) {
            $attrCode = $attr['attribute_code'];
            // Don't duplicate these values
            if (
                $attrCode != "type_id" 
                && $attrCode != "sku" 
                && $attrCode != "entity_id"
                && $attrCode != "visibility"
                && $attrCode != "url_key"
                && $attrCode != "url_path")
            {
                $product[$attrCode] = $masterProduct[$attrCode];
            }
        }
        // Add all of the stuff 
        $product->setTypeId('configurable');
        // It will create a configurable product with the master product's sku and append -C to the end. cannot duplicate skus
        $product->setSku(str_replace("-C", "", $masterProduct->sku));
        $product->setPrice($masterProduct->price);
        $product->setVisibilty(4); //catalog and search
        $product->setWebsiteIds(array(1));
        $product->setAttributeSetId($attrib->attribute_set_id); 
        $product->setCategoryIds($categories);
        $product->setName($masterProduct->name);
        $product->setDescription($masterProduct->description);
        $product->setShortDescription($masterProduct->short_description);
        $product->setStatus(1); 
        $product->setTaxClassId('2');
        $product->setFeaturedProduct('0');
        $product->setIsImported(0);
        $product->setWeight($masterProduct->weight);                
        $product->setCreatedAt(strtotime('now'));
        $product->product_type=$masterProduct->product_type;
        $product->vendor_code=$masterProduct->vendor_code;
        /* This is the configurable product attribute array
        We do a foreach loop and gather data from each sku's attrib array
        and create a new array for the new product based on what is to be 
        */
        // First, get the information about the master product from the database
        $db = Mage::getSingleton('core/resource')->getConnection('core_read');
        $sql="select * from 
                `nki_magentoV1.11.1.0`.catalog_eav_attribute AS A 
                INNER JOIN `YOUR_MAGENTO_DBNAME`.eav_attribute AS B ON A.attribute_id = B.attribute_id AND B.is_user_defined = 1 
                INNER JOIN `YOUR_MAGENTO_DBNAME`.eav_entity_attribute as EEA ON B.attribute_id = EEA.attribute_id
                WHERE EEA.attribute_set_id = " . $attrib->attribute_set_id . " AND A.is_configurable = 1 AND attribute_code != 'cost' AND B.source_model IS NOT null";
            //echo $sql;
        // Result Set
        $masterResult = $db->fetchAll($sql);
        $data = array();
        $retSku = array();
        foreach ($masterResult as $master) {
            $dataInner = array();
            // This section handles configurable product parameters based on the simple product's attributes
            $values = array();
            foreach ($sku as $prodsku) {
                $innerVals = array();
                // This gets the attribute of the current product
                try {
                    $productBySku = Mage::getModel('catalog/product')->loadByAttribute('sku',$prodsku);
                } catch (Exception $e)
                {
                    // Product cannot be loaded, so continue to next iteration of the loop
                    continue;
                }
                $attribVal = $productBySku[$master['attribute_code']];
                // Load up the attribute set and compare
                $attribute = $productBySku->getResource()->getAttribute($master['attribute_code']);
                $attributeInfo = Mage::getResourceModel('eav/entity_attribute_collection')
                    ->setCodeFilter($master['attribute_code'])
                    ->getFirstItem();
                // There is a possible chance that there is a null error occur here, however it is VERY
                // unlikely that attributeInfo will not be having a valid attribute loaded
                $attributeOptions = $attributeInfo->getSource()->getAllOptions(false);
                foreach ($attributeOptions as $option) {
                    if ($attribVal == $option['value']) {
                        $innerVals['value_index']=$option['value'];
                        $innerVals['label']=$option['label'];
                        $retSku[] = $prodsku;
                    } 
                }
                $innerVals['attribute_id']=$master['attribute_id'];
                if ($masterProduct['price'] != $productBySku['price']) {
                    $calcPrice = $masterProduct['price'] - $productBySku['price'];
                    $innerVals['pricing_value']=$calcPrice * -1;
                }
                else 
                {
                    $innerVals['pricing_value']= 0;
                }

                //$innerVals['pricing_value'] = '100';
                $innerVals['is_percent'] = '0';
                // Only add to the array if there was a value
                // return only the sku's added to the configurable product
                if ($innerVals['value_index'] <> NULL) {
                    $values[] = $innerVals;
                }

            }
            // Set the sata array for the configurable item
            $dataInner['id'] = NULL;
            $dataInner['label'] = $master['attribute_code'];
            $dataInner['position'] = NULL;
            $dataInner['attribute_id'] = $master['attribute_id'];
            $dataInner['frontend_label'] = $master['frontend_label'];
            $dataInner['html_id'] = 'config_super_product__attribute_0';
            $dataInner['values'] = $values;

            $data[] = $dataInner;   
        }
        $product->setConfigurableAttributesData($data);
        $product->setCanSaveConfigurableAttributes(1);
        // Set the stock data so it will appear on the site
        $stockData = $product->getStockData();
        $stockData['is_in_stock'] = 1;
        $stockData['use_config_manage_stockSpecified'] = true;
        $stockData['use_config_manage_stock'] = 0;
        $stockData['manage_stock'] = 1;
        $product->setStockData($stockData);
        // Finally save the product
        try{
            $product->save();
            $productId = $product->getId();
            //echo $product->getId() . ", $price, $itemNum added'n";
        }
        catch (Exception $e){ 
            // Saving the product failed
            $result = array (
                array(
                    'master_sku' => $master_sku,
                    'sku_list' => $sku_list,
                    'retval' => $e
                    )
            );
            error_log($e);
            return $result;
        } 
        // Add the associated products
        if ($productId > 0) {
            foreach($sku as $productSku) { 
                $productIdBySku = Mage::getModel('catalog/product')->loadByAttribute('sku',$productSku)->getId();
                // Add handler to not die on adding products that don't exist
                if ($producIdBySku > 0)
                {
                    $res = $this->addToConfigurable($productId, $productIdBySku);
                    /*                                              
                    if ($res == -5) 
                    {
                        $result = array (
                            array(
                                'master_sku' => $master_sku,
                                'sku_list' => $sku_list,
                                'retval' => ERR_ADD_ASSOCIATED_PROD_FAIL
                                )
                        );
                        return $result;
                    }
                    */
                }
            }
            $product->save();
            $stockItem = Mage::getModel('cataloginventory/stock_item');
            $stockItem->assignProduct($product);
            $stockItem->setData('is_in_stock', 1);
            $stockItem->setData('stock_id', 1);
            $stockItem->setData('store_id', 1);
            $stockItem->setData('manage_stock', 0);
            $stockItem->setData('use_config_manage_stock', 0);
            $stockItem->setData('min_sale_qty', 0);
            $stockItem->setData('use_config_min_sale_qty', 0);
            $stockItem->setData('max_sale_qty', 1000);
            $stockItem->setData('use_config_max_sale_qty', 0);
            $stockItem->save();

            //echo $productArray['product_id'];
        } else {
            // Something baaaaad happened
        }
    } catch (Exception $e) {
        // FATAL ERROR
        // Return php's fatal error that cannot be handled above (which should not happen, but might)
        die ( $e->getMessage() );
    }   
    echo "Configurable Product Created Successfully";
}