Script to set Base Image, Small Image and Thumbnail in Magento

Sometimes after products import in Magento you may face with situation where images were imported successfully but haven’t been set as Base Image, Small Image or Thumbnail. Script below will help you to fix it.

magento set image

So it is going to be a shell script that you can launch from command line. It will help us not to face with PHP execution time and memory limits. What is the plan of attack?

  • Firstly we grab all products ids that have ‘no_selection’ value in database (catalog_product_entity_varchar table) as Base Image.
  • Then get products ids that have missing image value record in catalog_product_entity_varchar table.
  • Next step is to combine those ids.
  • Get id to image relation from catalog_product_entity_media_gallery table.
  • Set Base Image / Small Image / Thumbnail.

For the last step we use saveAttribute method of product resource model. But please note that we have to modify this method to use default store id 0, otherwise you will set images for wrong store.

Here is how this method looks like:

//file app/code/local/Magebrew/SetImage/Model/Resource/Catalog/Product.php

    protected function _saveAttributeValue($object, $attribute, $value)
    {
        $write = $this->_getWriteAdapter();
        //set default store id
        $storeId = Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID;
        $table = $attribute->getBackend()->getTable();

        /**
         * If we work in single store mode all values should be saved just
         * for default store id
         * In this case we clear all not default values
         */
        if (Mage::app()->isSingleStoreMode()) {
            $storeId = $this->getDefaultStoreId();
            $write->delete($table, array(
                'attribute_id = ?' => $attribute->getAttributeId(),
                'entity_id = ?' => $object->getEntityId(),
                'store_id <> ?' => $storeId
            ));
        }

        $data = new Varien_Object(array(
            'entity_type_id' => $attribute->getEntityTypeId(),
            'attribute_id' => $attribute->getAttributeId(),
            'store_id' => $storeId,
            'entity_id' => $object->getEntityId(),
            'value' => $this->_prepareValueForSave($value, $attribute)
        ));
        $bind = $this->_prepareDataForTable($data, $table);

        if ($attribute->isScopeStore()) {
            /**
             * Update attribute value for store
             */
            $this->_attributeValuesToSave[$table][] = $bind;
        } else if ($attribute->isScopeWebsite() && $storeId != $this->getDefaultStoreId()) {
            /**
             * Update attribute value for website
             */
            $storeIds = Mage::app()->getStore($storeId)->getWebsite()->getStoreIds(true);
            foreach ($storeIds as $storeId) {
                $bind['store_id'] = (int)$storeId;
                $this->_attributeValuesToSave[$table][] = $bind;
            }
        } else {
            /**
             * Update global attribute value
             */
            $bind['store_id'] = $this->getDefaultStoreId();
            $this->_attributeValuesToSave[$table][] = $bind;
        }

        return $this;
    }

And finally our shell script:

//file shell/setBaseImage.php
require_once 'abstract.php';

class Magebrew_Set_Image extends Mage_Shell_Abstract
{
    /**
     * Run script
     *
     */
    public function run()
    {
        $installer = new Mage_Catalog_Model_Resource_Setup('core_setup');
        try {
            //grab all products ids that have 'no_selection' value in database
            $noSelectionSelect = $installer->getConnection()->select()
                ->from(
                    array('product' => $installer->getTable('catalog/product')),
                    array('id' => 'product.entity_id')
                )
                ->join(
                    array('varchar_table' => $installer->getTable('catalog_product_entity_varchar')),
                    'varchar_table.entity_id = product.entity_id',
                    array()
                )
                ->join(
                    array('eav_table' => $installer->getTable('eav/attribute')),
                    'varchar_table.attribute_id = eav_table.attribute_id',
                    array()
                )
                ->where('eav_table.attribute_code = "image" AND eav_table.entity_type_id = 4 AND varchar_table.value = "no_selection" AND varchar_table.store_id = 0');

            //get products ids that have missing image value record
            $missingImageValueSelectInner = $installer->getConnection()->select()
                ->from(
                    array('product' => $installer->getTable('catalog/product')),
                    array('id' => 'product.entity_id')
                )
                ->join(
                    array('varchar_table' => $installer->getTable('catalog_product_entity_varchar')),
                    'varchar_table.entity_id = product.entity_id',
                    array()
                )
                ->join(
                    array('eav_table' => $installer->getTable('eav/attribute')),
                    'varchar_table.attribute_id = eav_table.attribute_id',
                    array()
                )
                ->where('eav_table.attribute_code = "image" AND eav_table.entity_type_id = 4 AND varchar_table.store_id = 0');

            $missingImageValueSelect = $installer->getConnection()->select()
                ->from(
                    array('product' => $installer->getTable('catalog/product')),
                    array('id' => 'product.entity_id')
                )
                ->where('product.entity_id NOT IN ?', $missingImageValueSelectInner);

            //combine ids.
            $unitedSselect = $installer->getConnection()->select()->union(array($noSelectionSelect, $missingImageValueSelect));
            $ids = $installer->getConnection()->fetchCol($unitedSselect);
            Mage::log(sprintf("found %s candidats for setting image", count($ids)), null, 'image_set.log', true);

            //Get id to image relation from catalog_product_entity_media_gallery table
            $mediaSelect = $installer->getConnection()->select()
                ->from(array('gallery' => $installer->getTable('catalog_product_entity_media_gallery')), array('id' => 'entity_id', 'value'))
                ->join(
                    array('gallery_value' => $installer->getTable('catalog_product_entity_media_gallery_value')),
                    'gallery_value.value_id = gallery.value_id AND store_id = 0',
                    array()
                )
                ->where('entity_id in (?)', $ids)
                ->order('position asc');
            $query = $installer->getConnection()->query($mediaSelect);
            $idToImage = array();
            while ($row = $query->fetch()) {
                if (!isset($idToImage[$row['id']])) {
                    $idToImage[$row['id']] = $row['value'];
                }
            }

            //Mage::log($idToImage, null, 'image_set.log', true);
            /** @var Magebrew_SetImage_Model_Resource_Catalog_Product $resource */
            $resource = Mage::getModel('magebrew_setimage/resource_catalog_product');
            foreach ($idToImage as $id => $image) {
                $product = Mage::getModel('catalog/product')->setId($id);
                $product->setStoreId(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID);
                $product->setImage($image);
                $product->setSmallImage($image);
                $product->setThumbnail($image);
                Mage::log(sprintf("trying to set image %s to product %s", $image, $id), null, 'image_set.log', true);
                $resource->saveAttribute($product, 'image');
                $resource->saveAttribute($product, 'small_image');
                $resource->saveAttribute($product, 'thumbnail');
                echo 'set images for product ' . $id . PHP_EOL;
            }
            echo 'Finished' . PHP_EOL;
        } catch (Exception $e) {
            echo $e->getMessage() . "\n";
        }
    }
}

$shell = new Magebrew_Set_Image();
$shell->run();

For complete solution clone this repo, copy files and run script:

php shell/setBaseImage.php

Your comments are welcome.