22

This must be a such a simple programming task that I absolutely cannot find any information about it on the net. Basically, I'm trying to DELETE product images. I want to delete all images from a product's media gallery. Can I do this without wading through a million lines of code for such a simple task?

Please note that I've already tried this:

$attributes = $product->getTypeInstance()->getSetAttributes();
if (isset($attributes['media_gallery'])) {
    $gallery = $attributes['media_gallery'];
    $galleryData = $product->getMediaGallery();//this returns NULL

    foreach($galleryData['images'] as $image){
        if ($gallery->getBackend()->getImage($product, $image['file'])) {
            $gallery->getBackend()->removeImage($product, $image['file']);
        }
    }
}

This absolutely does not work. I'm trying to delete images during an import so that I do not keep accruing duplicates. Any help would be greatly appreciated.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • http://stackoverflow.com/questions/5328763/magento-re-importing-of-products/5381586 Looks like the same code you have already but may offer some insight, have you made sure media/ is accessible ? – B00MER Apr 18 '11 at 22:33
  • Can you provide some error messaging or other information to help debug why its not working? – Jonathan Day Apr 19 '11 at 03:14
  • Boomer, my /media/catalog directory has mode 777 down the tree. –  Apr 19 '11 at 12:51
  • Jonathan, the problem is that $product->getMediaGallery() returns NULL even though there is a media gallery and there are images. Even $product->getImage() returns an image. Something must have changed since version 1.4. –  Apr 19 '11 at 12:54
  • Mage::getModel('catalog/product')->load($id)->getMediaGallery() seems to work fine for me.. Did you load the product correctly? – Lucas Moeskops Apr 05 '12 at 15:28
  • This one is also useful https://www.magentocommerce.com/magento-connect/image-clean.html – Sarfaraz bheda Aug 20 '16 at 13:19

14 Answers14

47

Okay, this is how I finally fixed my problem.

if ($product->getId()){
    $mediaApi = Mage::getModel("catalog/product_attribute_media_api");
    $items = $mediaApi->items($product->getId());
    foreach($items as $item)
        $mediaApi->remove($product->getId(), $item['file']);
}

This is the link that finally set my head straight: http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_product_attribute_media

Too bad it's not as simple as $product->getImages(), eh?

  • I could really use this, can i ask in which file do we have to enter this code? if ($product->getId()){ $mediaApi = Mage::getModel("catalog/product_attribute_media_api"); $items = $mediaApi->items($product->getId()); foreach($items as $item) $mediaApi->remove($product->getId(), $item['file']); } –  Jun 13 '11 at 10:26
  • The above code was used in a custom module. You need a programmer with a specific task to accomplish using the above code. –  Jun 18 '11 at 16:05
  • 12
    Quick Note: Modern versions of Magento won't let you programmatically save a product if the store object's ID isn't set to the admin store's id ("0"). If you're using the above from a frontend store context, be sure to call `Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);` first. – Alana Storm Sep 19 '12 at 21:22
  • @Colin Tickle's answer is the solution that worked for me, this is in some add product automatically integration where other solutions have fallen short. – Henry's Cat Jul 24 '17 at 11:02
9

In Magento 1.7.0.2 I use this code for remove all images from a product gallery:

//deleting
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
$items = $mediaApi->items($product->getId());
$attributes = $product->getTypeInstance()->getSetAttributes();
$gallery = $attributes['media_gallery'];
foreach($items as $item){
    if ($gallery->getBackend()->getImage($product, $item['file'])) {
        $gallery->getBackend()->removeImage($product, $item['file']);
    }
}
$product->save();

With code from Davids Tay answer, I got the error: Fatal error: Uncaught exception ‘Mage_Eav_Model_Entity_Attribute_Exception’ with message ‘SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (base_xxx.catalog_product_entity_media_gallery_value, CONSTRAINT FK_CAT_PRD_ENTT_MDA_GLR_VAL_VAL_ID_CAT_PRD_ENTT_MDA_GLR_VAL_ID FOREIGN KEY (value_id) REFERENCES `catalog_prod)’

8

To remove all images from a product gallery:

$product = Mage::getModel('catalog/product')->load($id);
$mediaGalleryAttribute = Mage::getModel('catalog/resource_eav_attribute')->loadByCode($entityTypeId, 'media_gallery');
$gallery = $product->getMediaGalleryImages();
foreach ($gallery as $image)
    $mediaGalleryAttribute->getBackend()->removeImage($product, $image->getFile());
$product->save();
Pihtt
  • 81
  • 1
  • 2
5

During deleting of images I found one interesting thing. When you try this code:

$galleryData = $product->getMediaGallery(); //this returns NULL

Media gallery object depends on how your product was created, if:

$product = Mage::getModel('catalog/product')->loadByAttr('sku', $sku);

then media gallery will be empty, if:

$product = Mage::getModel('catalog/product')->load($id);

then media gallery is object and you can use this object to delete images from db. To delete images from file system you have to add such code:

@unlink(Mage::getBaseDir('media') . '\catalog\product\' . $image['file']);

but if you want to change image and name it like previous image (image1.png replace with image1.png) in this case you will have browser caching issue.

Also you can try to load media gallery for product:

$product->getResource()->getAttribute('media_gallery')->getBackend()->afterLoad($product);
Viacheslav Kondratiuk
  • 8,493
  • 9
  • 49
  • 81
4

This is the code I finally decided to use for this task.

protected function _removeMediaGalleryImages(Mage_Catalog_Model_Product $product)
{
    $mediaGalleryData = $product->getMediaGallery();
    if (!isset($mediaGalleryData['images']) || !is_array($mediaGalleryData['images'])) {
        return;
    }

    $toDelete = array();
    foreach ($mediaGalleryData['images'] as $image) {
        $toDelete[] = $image['value_id'];
    }
    Mage::getResourceModel('catalog/product_attribute_backend_media')->deleteGallery($toDelete);
}
3
     Just use this code to create .php file and place it to root folder of magento.

    <?php 
    require_once 'app/Mage.php';

    Mage::app();
    Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);

    $products = Mage::getModel('catalog/product')->getCollection();
      //->addAttributeToFilter('entity_id', array('gt' => 14000));

    $mediaApi = Mage::getModel("catalog/product_attribute_media_api");

    foreach($products as $product) {
        $prodID = $product->getId();
        $_product = Mage::getModel('catalog/product')->load($prodID);
        $items = $mediaApi->items($_product->getId());
        foreach($items as $item) {
            $mediaApi->remove($_product->getId(), $item['file']);
        }
    }
?>
Ramesh
  • 192
  • 1
3

Hopefully this answer isn't unwelcome, as it's technically not a solution achieved via Magento programming as you ask, but I have successfully purged all gallery images myself for the same purpose simply by truncating the relevant tables in Magento 1.4.2.0 (I believe it's the same table structure in 1.5 as well).

TRUNCATE TABLE `catalog_product_entity_media_gallery`
TRUNCATE TABLE `catalog_product_entity_media_gallery_value`

Then follow up by removing all the image files within the /media/catalog/product directory.

I did look for a way to do this programmatically myself, but found this much more efficient and have experienced no negative side effects.

CVM
  • 780
  • 1
  • 6
  • 10
  • 5
    really TRUNCATE ? on heavy related data structure this just screams for future troubles as truncate sets your increment id-s to 0 and expect wrong data relations from this point on. DELETE is the one you are looking if at all. – Anton S Apr 19 '11 at 06:28
  • CVM, lol, I need to delete images from specific products only, not wipe out my entire catalog. –  Apr 19 '11 at 12:56
  • 1
    Point completely understood on the TRUNCATE, this did cross my mind. However, on inspecting how the tables relate to the products they reference the product entity IDs but crucially the other product tables don't reference any of the image gallery IDs. So their removal is safe. @David, I'll have a crack at this with code later, see if I can find the answer. – CVM Apr 20 '11 at 13:40
1

What About this

Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
    $mediaApi = Mage::getModel("catalog/product_attribute_media_api");
    $items = $mediaApi->items($product->getId());
    $attributes = $product->getTypeInstance()->getSetAttributes();
    $gallery = $attributes['media_gallery'];
    foreach($items as $item){
        if ($gallery->getBackend()->getImage($product, $item['file'])) {
            $gallery->getBackend()->removeImage($product, $item['file']);
        }
    }
    $product->save();
Vinay Sikarwar
  • 456
  • 7
  • 21
1

Fastest way to remove image,then follow below steps: delete all records from

  1. catalog_product_entity_media_gallery
  2. catalog_product_entity_media_gallery_value'

table because magento is save all product image data at those table.

Then index from Index management from admin for set image black.

Then remove image from dir then goto Your magento dir at media/catalog/product and from this folder delete all file.

Another Process:

Andy Simpson,you need a script which is delete all product from your system which will delete from DB and file system.

Step1: Create a php at root direct of magento system which include Mage.php at first code.

require_once "YOURMAGENTODIR/app/Mage.php";
umask(0);

Step2: set current store is admin and set Developer mode

Mage::app('admin');
Mage::setIsDeveloperMode(true);

Step3: Get Product Collection and create a loop for get one product by one by one

$productCollection=Mage::getResourceModel('catalog/product_collection');

Step4: fetch product image by one and remove image one using below code:

$remove=Mage::getModel('catalog/product_attribute_media_api')->remove($product->getId(),$eachImge['file']);

FULL CODE:

<?php
require_once "YOURMAGENTODIR/app/Mage.php";
umask(0);
Mage::app('admin');
Mage::setIsDeveloperMode(true);

$productCollection=Mage::getResourceModel('catalog/product_collection');
foreach($productCollection as $product){
echo $product->getId();
echo "<br/>";
         $MediaDir=Mage::getConfig()->getOptions()->getMediaDir();
        echo $MediaCatalogDir=$MediaDir .DS . 'catalog' . DS . 'product';
echo "<br/>";

$MediaGallery=Mage::getModel('catalog/product_attribute_media_api')->items($product->getId());
echo "<pre>";
print_r($MediaGallery);
echo "</pre>";

    foreach($MediaGallery as $eachImge){
        $MediaDir=Mage::getConfig()->getOptions()->getMediaDir();
        $MediaCatalogDir=$MediaDir .DS . 'catalog' . DS . 'product';
        $DirImagePath=str_replace("/",DS,$eachImge['file']);
        $DirImagePath=$DirImagePath;
        // remove file from Dir

        $io     = new Varien_Io_File();
         $io->rm($MediaCatalogDir.$DirImagePath);

        $remove=Mage::getModel('catalog/product_attribute_media_api')->remove($product->getId(),$eachImge['file']);
    }


}
Amit Bera
  • 7,581
  • 7
  • 31
  • 57
1

If you want to remove more products like 1000 or 5000 then use bottom one with direct query.

Before try this one take backup of your database

<?php
require_once 'app/Mage.php';
umask(0);
Mage::app();
set_time_limit(0);
ini_set('display_error','1');


$resource = Mage::getSingleton('core/resource');
$connection = $resource->getConnection('core_write');

$id = 101;
$product = Mage::getModel('catalog/product')->load($id);

$q = "DELETE FROM `catalog_product_entity_media_gallery` where entity_id = '".$product->getId()."'"; 

$connection->query($q);

?>
1

Accessing the Database for such things is a bad idea. You can delete images ( or reorder them by changing the 'position' value ) using the following snippet in a custom module ( for the sake of simplicity i'm using ObjectManager, but you should place ProductFactory and ProductRepositoryInterface in the constructor )

$objectManager = ObjectManager::getInstance();

//Get ProductFactory in order to instatiate the Product Object 
$productFactory = $objectManager->get('\Magento\Catalog\Model\ProductFactory');

//We have to use ProductRepositoryInterface in order to save the changes bellow to the product
$productRepository = $objectManager->get('\Magento\Catalog\Api\ProductRepositoryInterface');

//Load a Product by ID in this case 1
$product = $productFactory->create()->load(1);

//Gets an array containing arrays representing each image in the gallery
$mediaGalleryEntries = $product->getMediaGalleryEntries();

//Here we delete every image, you can use conditions in foreach
foreach ($mediaGalleryEntries as $key => $imageEntry) {
    unset($mediaGalleryEntries[$key]);
}

//Finally set the altered entries and save using productRepository
$product->setMediaGalleryEntries($mediaGalleryEntries);
$productRepository->save($product);

The code above tested in Magento 2.3 and it also removes images from the filesystem. You can use it to either delete or alter an entry ( change position, image roles etc )

To view each imageEntry you can access its data using $imageEntry->getData()

sarakinos
  • 666
  • 11
  • 28
0
DELETE FROM catalog_product_entity_media_gallery WHERE value_id NOT IN (SELECT * FROM (SELECT MIN(value_id) FROM `catalog_product_entity_media_gallery` GROUP BY LEFT(value,17), entity_id  having count(*) > 1) x)

why 17 ?

The expamle you have duplicate like this:

/0/0/000116810609_1.jpg

/0/0/000116810609_2.jpg

/0/0/000116810609_3.jpg

/0/0/000116810609_4.jpg

LEFT(value,17)

/0/0/000116810609

/0/0/000116810609

/0/0/000116810609

/0/0/000116810609

No they are duplicates ;)

0

Place the below script in magento root and execute

 <?php

  require_once("app/Mage.php");
  umask(0);
   Mage::app();
   $ob = new Clean();
   $ob->removemedia();

 Class Clean {

 function removemedia() {
$read = Mage::getSingleton('core/resource')->getConnection('core_read');
$select = $read->select()
        ->from('catalog_product_entity_media_gallery', '*')
        ->group(array('value_id'));

$flushImages = $read->fetchAll($select);
echo count($flushImages);
$array = array();
foreach ($flushImages as $item1) {
    $array[] = $item1['value'];
}

$valores = $array;

$pepe = 'media' . DS . 'catalog' . DS . 'product';

$leer = $this->listDirectories($pepe);

foreach ($leer as $item) {
    try {
        $item = strtr($item, '\\', '/');
        if (!in_array($item, $valores)) {
            $valdir[]['filename'] = $item;
            unlink('media/catalog/product' . $item);
        }
    } catch (Zend_Db_Exception $e) {

    } catch (Exception $e) {
        //Mage::log($e->getMessage());
    }
  }
 }

function listDirectories($path) {
    if (is_dir($path)) {
       if ($dir = opendir($path)) {
        while (($entry = readdir($dir)) !== false) {
            if (preg_match('/^\./', $entry) != 1) {
                if (is_dir($path . DS . $entry) && !in_array($entry, array('cache', 'watermark'))) {
                    $this->listDirectories($path . DS . $entry);
                } elseif (!in_array($entry, array('cache', 'watermark')) && (strpos($entry, '.') != 0)) {
                    $this->result[] = substr($path . DS . $entry, 21);
                }
            }
        }
        closedir($dir);
    }
 }
 return $this->result;
 }

  }
0

I had to do something similar not too long ago - needed to replace all product images during an import.

This link helped a lot: http://www.sharpdotinc.com/mdost/2010/03/02/magento-import-multiple-images-or-remove-images-durring-batch-import/

Hopefully it will give you a nudge in the right direction.

monkey do
  • 306
  • 1
  • 4