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

Time:03-14

I have a script that creates a configurable product and the simple products associated to it. After the creation, in the backend, all of them seems fine (stock, website, status, visibility and association between the simple products and the configurable are ok). The problem is when I try to search for the configurable product or add it to a category, it doesn't display.

All products (configurable and simple) are firstly created with this method:

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

In case the product is configurable, it then goes to this method:

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

Where the method setAssociateAttributes() set the attributes IDs of the configurable product being created:

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

After that, the configurable product returned in setData() is saved using $product->save(). Then, the simple product's are created (using the createBaseProduct() method), saved, and assigned to the configurable product using this method:

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

And all seems good, products are created and correctly assigned to configurable. But in the frontend the configurable product isn't displayed (only if I access it via URL it opens correctly, with the variations and all). Obs.: simple products are displayed in search correctly, only the configurable is missing.

I believe there's something wrong in the configurable's data, but I can't figure it out :(

----- EDIT -----

So I debugged it a little more and seems that the problem is actually in the attribute used to create the configurable product (I'm also creating this attribute programmatically). If I save the attribute created programatically again, in my admin panel, the link between simple products and their configurable disapear (they don't show linked in the admin panel anymore).The attribute is created before the configurable product using 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();
}

And this attribute is set to child products (during their creation) using the following method:

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

Where the method $customAttribute->addOptionIfNotExists() creates the attribute's option if not already created:

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

And after added the method associateChildProduct() is called to associate simple products to their configurable.

Obs.: configurable product is displayed correctly via URL, even the attribute variations are shown. Obs2.: if I save the attribute via admin panel, delete simple products and create new ones using "Quick create" (with the same values) the configurable product is displayed in search and categories.

CodePudding user response:

Just to put my comments in form of an answer, and organize it...

There are many reasons for a recently created product or one created programmatically to not being displayed in some collection.

Index

The first and most common one is related to indexation.
This could be related to issues in the cronjob (not configured, or not working properly).
You can manually trigger the reindex process by doing:
Magento 1: php shell/indexer.php reindexall
Magento 2: bin/magento indexer:reindex

Product not added to the website or not visible

Check if the product is enabled and visible in catalog. If they are simple products from a configurable product, make sure they are both enabled. Also check if there is enough inventory of the item and if they are not marked as "out of inventory" (regardless the stock qty).
In multi website stores, check the "Website" group in the product edit page, and see if it's checked to appear in that website. Also check the product scope. Sometimes you disable the product in a inner level (i.e. store view or website).

Some condition is not met

If you believe that you've checked everything, now it's time to debug the collection.
Magento 1 and Magento 2 have the getSelect() method available in collection objects.
Find the phtml or block where your products are being looped, and find the collection variable (generally used in the foreach).
Then, add something like echo (string)$collection->getSelect().
This will show the query used to search the products. See which join or where condition is not met by your missing product.
Here's an example of category collection queries in 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' category from Magento 1 sample data.

CodePudding user response:

With 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).

So I changed my code for attribute's creation to:

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

Where in the indicated line the attribute's backend_type is set to int. After this, the configurable product is now being correctly displayed in category and search :)

  • Related