Magento API:将预先存在的简单产品分配给可配置产品

Posted

技术标签:

【中文标题】Magento API:将预先存在的简单产品分配给可配置产品【英文标题】:Magento API: Assigning preexisting simple products to configurable products 【发布时间】:2010-10-28 02:54:22 【问题描述】:

我有一个包含大量库存商品的客户数据库,这些商品作为简单产品上传到 Magento。

现在我需要将它们分组并将它们分配给可配置的产品,它们的尺寸和颜色是它们的可配置属性。

Magento API 有一个 Product_Link 类,它有一个看起来很有前途的方法:catalogue-product-link.assign (link),但我无法终生弄清楚我需要什么参数才能让它工作对于可配置产品,前提是 assign 本来就是这样使用的。

【问题讨论】:

Magento 文档是垃圾,不是吗。 哦,我听到了!我时不时地从他们那里收到垃圾邮件来实际购买用户文档。噗! 是的,我也通过 Twitter 收到了他们的“建议”。其实我已经买了官方的用户指南,对开发者来说没什么用。还买了php|architect的书,很好读但是应该厚10倍。 这是一个可以提供帮助的扩展:johannreinke.com/en/2012/04/20/… 安装后,您只需为可配置产品指定一个键“associated_skus”,简单的产品将自动关联。 【参考方案1】:

嗯,这里的笔记帮助我完成了这项工作。因此,我想与您分享将简单产品添加到现有可配置产品的代码。

此代码假定简单产品是一个有效的添加,我不确定如果不是会发生什么。

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 ) );                

【讨论】:

我正在尝试从命令行脚本执行此操作,但在这里失败了: $loader = Mage::getResourceModel( 'catalog/product_type_configurable' )->load( $_configurableProduct ); (第一行)有什么想法吗?我目前正在调查它,如果有结果会通知。 我更新了 Scimon 的代码以再次在最新版本的 magento 中工作:see below【参考方案2】:

Scimon 接受的答案中的代码在最近版本的 magento 中不再有效(至少在 1.7 中)。但幸运的是,您只需要一个小修复就可以让它再次工作:

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 ) );                

【讨论】:

我有一个例外的答案?不久前,我已经有一年左右没有进行任何 Magento 开发了,所以继续吧。 这可能应该是对接受的答案恕我直言的编辑。 @Joseph:在撰写本文时,我没有足够的声誉来这样做,所以我确实发布了一个新答案。【参考方案3】:

我现在正在做这件事。

到目前为止,我发现这些项目作为参考很有帮助:

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/

到目前为止,我将发布我的代码,并希望在它工作后更新它..

// 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";

好的,这使用“item_size”作为区分“简单”产品的属性。此外,这假定“可配置”父 SKU 是子 SKU 的根。例如,ABC001 是父级,而 ABC001-SMALL 和 ABC001-LARGE 是简单的子级。

希望对某人有所帮助。

【讨论】:

我不知道你是否还在做这个,但我想我已经破解了。【参考方案4】:

我这是一个未受过教育的猜测,但我认为你的要求不能用现有的 API 完成。您必须自己编写或直接访问数据库。

【讨论】:

使用他们使用的 EAV 数据库模式,在直接访问数据库时没有“只是”。痛苦!!!【参考方案5】:

这是我直接用 PHP 做的 hack-y 方式。有三个相关的表。我使用颜色和大小作为我的属性。 我的父产品(可配置)实际上并不存在于我的目录中。它们本质上是模型级别,然后产品是 SKU 级别。 所以 LIKE 'parentproductsku%' 适合孩子们。

$query1 = "SELECT * FROM mage_catalog_product_entity WHERE type_id= 'configurable'";
    //Find the parent id
    $statusMessage = "Ok, found a product with a confgurable attribute";
    $result1 = $this->runQuery($query1, "query1", $statusMessage);
    while ($row1 = mysql_fetch_assoc($result1))  //entering the first loop where products are configurable
        $this->parentId = $row1['entity_id'];
        $this->parentSku = $row1['sku'];

        echo "The SKU was $this->parentSku" . "<br />";

    //insert these into the link table for association
    $query2 = "SELECT * FROM mage_catalog_product_entity WHERE type_id= 'simple' AND sku LIKE '" . $this->parentSku . "%';";
    // find the child ids that belong to the parent
    $statusMessage = "Found some children for $this->parentSku";
    $result2 = $this->runQuery($query2, "query2", $statusMessage);
    while ($row2 = mysql_fetch_assoc($result2)) //entering the second loop where SKU is like model sku
        $this->childId = $row2['entity_id'];
        $this->childSku = $row2['sku'];

        echo "Now we're working with a child SKU $this->childSku" . "<br />";

        //"REPLACE INTO catalog_product_super_attribute SET product_id='".$product->entity_id."', attribute_id='".$attribute->attribute_id."', position='".$position."'";
        $query3 = "REPLACE INTO mage_catalog_product_super_attribute  (product_id, attribute_id, position) VALUES ('" . $this->childId . "', '76', '0');";
        $message3 = "Inserted attribute for color for ID $this->childId SKU $this->childSku";
        $result3 = $this->runQuery($query3, "query3", $message3);

        $query4 = "REPLACE  INTO mage_catalog_product_super_attribute_label (product_super_attribute_id, store_id, use_default, value) VALUES (LAST_REPLACE_ID(), '0', '0', 'Color');";
        $message4 = "Inserted attribute for Color  SKU $this->childSku ID was $this->db->insert_id";
        $result4 = $this->runQuery($query4, "query4", $message4);

        $query5 = "REPLACE  INTO mage_catalog_product_super_attribute  (product_id, attribute_id, position) VALUES ('" . $this->childId . "', '529', '0');";
        $message5 = "Inserted attribute for Product Size SKU $this->childSku";
        $result5= $this->runQuery($query5, "query5", $message5);


        $query6 = "REPLACE  INTO mage_catalog_product_super_attribute_label (product_super_attribute_id, store_id, use_default, value) VALUES (LAST_REPLACE_ID(), '0', '0', 'Size');";
        $message6 = "Inserted attribute for Size SKU $this->childSku ID was $this->db->insert_id";
        $result6 = $this->runQuery($query6, "query6", $message6);

        $query7 = "REPLACE INTO mage_catalog_product_super_link (product_id, parent_id) VALUES ('" . $this->childId . "', '" . $this->parentId . "');";
        $message7 = "Inserted $this->childId and $this->parentId into the link table";
        $result7 = $this->runQuery($query7, "query7", $message7);

        $query8 = "REPLACE INTO mage_catalog_product_relation (parent_id, child_id) VALUES ('" . $this->parentId . "', '" . $this->childId . "');";
        $message8 = "Inserted $this->childId and $this->parentId into the link table";
        $result8 = $this->runQuery($query8, "query8", $message8);

         //end while row 2 the child ID

             //end while row 1 the parent id

【讨论】:

【参考方案6】:

令人惊讶的是,如果您所有的简单产品价格相同,这会奏效:

        $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();

【讨论】:

【参考方案7】:

@aeno 的解决方案对我不起作用,所以我对其进行了一些改进。这已经使用通过Mage::getModel( 'catalog/product' )-&gt;load() 方法实例化的产品进行了测试。

private function _attachProductToConfigurable( $childProduct, $configurableProduct )

    $childIds   = $configurableProduct->getTypeInstance()->getUsedProductIds();
    $childIds[] = $childProduct->getId();
    $childIds   = array_unique( $childIds );

    Mage::getResourceModel( 'catalog/product_type_configurable' )
        ->saveProducts( $configurableProduct, $childIds );

【讨论】:

以上是关于Magento API:将预先存在的简单产品分配给可配置产品的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式在magento中为产品分配类别

Magento 将产品批量分配到类别

Magento 2:“请求的产品不存在。验证产品并重试。”

产品没有出现在Magento2子类别上

magento 1.9 新添加的产品没有显示在分类页面?

Magento 1.5.1:导入产品时出现“图像不存在”