以编程方式创建的可配置产品未显示在搜索中 - Magento 1.9

Configurable product created programmatically doesn't show in search - Magento 1.9

我有一个脚本可以创建可配置的产品以及与其关联的简单产品。创建后,在后端,所有这些看起来都很好(股票、网站、状态、可见性和简单产品与可配置产品之间的关联都可以)。问题是当我尝试搜索可配置产品或将其添加到类别时,它没有显示。

所有产品(可配置和简单)首先使用此方法创建:

private function createBaseProduct($sku)
    {
        $_product = Mage::getModel('catalog/product');
        $_product->setSku($sku);
        $_product->setAttributeSetId(4);
        $_product->setTypeId('simple');
        $_product->setWebsiteIDs(array(1));
        $_product->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
        $_product->setStatus(1);
        $_product->setTaxClassId(0);
        $_product->setStockData(array(
            'use_config_manage_stock' => 0,
            'manage_stock' => 1,
            'is_in_stock' => 1,
            'qty' => 100
        ));
        return $_product;
    }

如果产品是可配置的,则转到此方法:

private function setData($configurable)
    {
        $configurable->setTypeId('configurable');
        $configurable->setStockData(array(
            'use_config_manage_stock' => 0,
            'manage_stock' => 0,
            'is_in_stock' => 1,
            'qty' => 0,
        ));
    --> $configurable = $this->setAssociativeAttributes($configurable); 
        $configurableAttributesData = $configurable->getTypeInstance()->getConfigurableAttributesAsArray();
        $configurable->setCanSaveConfigurableAttributes(true);
        $configurable->setConfigurableAttributesData($configurableAttributesData);
        return $configurable;
    }

其中方法 setAssociateAttributes() 设置正在创建的可配置产品的属性 ID:

 private function setAssociativeAttributes()
    {
        $configurable->getTypeInstance()->setUsedProductAttributeIds($this->configurableAttrsIds);
        return $configurable;
    }

之后,setData()返回的可配置产品使用$product->save()保存。然后,创建简单产品(使用 createBaseProduct() 方法)、保存并分配给使用此方法的可配置产品:

public function associateChildProduct($configurableId, $childProduct)
    {
        $configurable = Mage::getModel('catalog/product')->load($configurableId); 
        $childProducts = $configurable->getTypeInstance()->getUsedProducts();
        array_push($childProducts, $childProduct);
        $childProductsIds = array();
        foreach($childProducts as $product) {
            array_push($childProductsIds, $product->getId());
        }
        Mage::getResourceSingleton('catalog/product_type_configurable')
            ->saveProducts($configurable, $childProductsIds);
    }

一切似乎都很好,产品已创建并正确分配给可配置。但是在前端没有显示可配置的产品(只有当我通过 URL 访问它时,它才能正确打开,包括变体和所有)。 观察:简单的产品在搜索中正确显​​示,只有可配置的缺失。

我认为可配置的数据有问题,但我无法弄清楚:(

----- 编辑 -----

所以我稍微调试了一下,似乎问题实际上出在用于创建可配置产品的属性中(我也是以编程方式创建此属性)。如果我再次保存以编程方式创建的属性,在我的管理面板中,简单产品及其可配置之间的 link 消失(它们不再在管理面板中显示 linked)。属性已创建在使用 class "CustomAttribute":

的可配置产品之前
public function __construct($attrCode)
{   
    $attrData = array(
            'group'             => '',
            'type'              => 'varchar',
            'backend'           => '',
            'frontend'          => '',
            'label'             => ucfirst($attrCode),
            'input'             => 'select',
            'class'             => '',
            'source'            => '',
            'global'            => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
            'visible'           => true,
            'required'          => false,
            'user_defined'      => true,
            'default'           => '0',
            'searchable'        => false,
            'filterable'        => false,
            'comparable'        => false,
            'visible_on_front'  => false,
            'is_configurable'   => true,
            'unique'            => false,
        );
        $installer = new Mage_Eav_Model_Entity_Setup('core_setup');
        $installer->startSetup();
        $installer->addAttribute(Mage_Catalog_Model_Product::ENTITY, $attrCode, $attributeData);
        $this->addAttributeToDefaultSet();
        $installer->endSetup();
}

并使用以下方法将此属性设置为子产品(在创建期间):

private function setCustomAttribute($chidlProduct, $attrCode, $optionLabel)
{
    $customAttribute = new CustomAttribute($attrCode);
    $customAttribute->addOptionIfNotExists($optionLabel, $attrCode);
    $optionId = $customAttribute->getOptionId($optionLabel);
    $product->setData($attrCode, $optionId);
}

方法 $customAttribute->addOptionIfNotExists() 创建属性选项的位置(如果尚未创建):

public function addOptionIfNotExists($optionLabel, $attrCode)
    {
        $value['option'] = array($optionLabel);
        $order['option'] = 0;
        $optionData = array(
            'value' => $value,
            'order' => $order
        );
        $attribute = Mage::getSingleton('eav/config')
            ->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attrCode);
        $attribute->setData('option', $optionData);
        $attribute->save();
    }

添加后调用方法 associateChildProduct() 将简单产品与其可配置相关联。

观察:可配置产品通过 URL 正确显示,甚至显示属性变化。 Obs2.: 如果我通过管理面板保存属性,删除简单产品并使用“快速创建”创建新产品(具有相同的值),可配置产品将显示在搜索和类别中。

只是把我的评论以答案的形式整理一下...

最近创建的产品或以编程方式创建的产品未显示在某些集合中的原因有很多。

索引

第一个也是最常见的一个与索引有关。
这可能与 cronjob 中的问题有关(未配置或无法正常工作)。
您可以通过执行以下操作手动触发重建索引过程:
Magento 1php shell/indexer.php reindexall
Magento 2bin/magento indexer:reindex

产品未添加到网站或不可见

检查产品是否已启用并在目录中可见。如果它们是来自可配置产品的简单产品,请确保它们都已启用。 还要检查商品是否有足够的库存,以及它们是否未标记为“缺货”(无论库存数量如何)。
在多网站店铺中,勾选商品编辑页面的“网站”组,看是否勾选出现在该网站。还要检查产品范围。有时您会在内部级别(即商店视图或网站)禁用产品。

不满足某些条件

如果您认为自己已经检查了所有内容,那么现在是调试集合的时候了。
Magento 1 和 Magento 2 在集合对象中有 getSelect() 方法。
找到您的产品正在 循环 的 phtml 或块,并找到集合变量(通常在 foreach 中使用)。
然后,添加类似 echo (string)$collection->getSelect().
的内容 这将显示用于搜索产品的查询。查看您丢失的产品不满足哪个 joinwhere 条件。
下面是 Magento 中类别集合查询的示例 1:

SELECT `e`.*,
       `cat_index`.`position`    AS `cat_index_position`,
       `price_index`.`price`,
       `price_index`.`tax_class_id`,
       `price_index`.`final_price`,
       IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price),
          price_index.min_price) AS `minimal_price`,
       `price_index`.`min_price`,
       `price_index`.`max_price`,
       `price_index`.`tier_price`
FROM `catalog_product_entity` AS `e`
INNER JOIN `catalog_category_product_index` AS `cat_index`
        ON cat_index.product_id = e.entity_id AND cat_index.store_id = 4 AND
           cat_index.visibility IN (2, 4) AND cat_index.category_id = '10'
INNER JOIN `catalog_product_index_price` AS `price_index`
        ON price_index.entity_id = e.entity_id AND price_index.website_id = '4' AND
           price_index.customer_group_id = 0
ORDER BY `cat_index`.`position` ASC
LIMIT 12

1 'New Arrivals' 来自 Magento 1 示例数据的类别。

Ricardo Martins help I was able to debug the problem and discover that the configurable product wasn't being displayed because it's entity_id wasn't being added to the table catalog_product_index_price. This problem seems to be caused because the attribute used in the configurable product's creation had the backend_type set to varchar, instead int (Reference).

所以我将创建属性的代码更改为:

public function __construct($attrCode)
{   
    $attrData = array(
            'group'             => '',
        --> 'type'              => 'int',
            'backend'           => '',
            'frontend'          => '',
            'label'             => ucfirst($attrCode),
            'input'             => 'select',
            'class'             => '',
            'source'            => '',
            'global'            => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
            'visible'           => true,
            'required'          => false,
            'user_defined'      => true,
            'default'           => '0',
            'searchable'        => false,
            'filterable'        => false,
            'comparable'        => false,
            'visible_on_front'  => false,
            'is_configurable'   => true,
            'unique'            => false,
        );
        $installer = new Mage_Eav_Model_Entity_Setup('core_setup');
        $installer->startSetup();
        $installer->addAttribute(Mage_Catalog_Model_Product::ENTITY, $attrCode, $attributeData); 
        $this->addAttributeToDefaultSet();
        $installer->endSetup();
}

在指示的行中,属性的 backend_type 设置为 int。在此之后,可配置产品现在可以正确显示在类别和搜索中 :)