18

I want to upload images to the existing products. The images are in import_dir. And they need to be added to the product that already exists in the catalog.

I could find only 2 ways how to do it.
1. "Bad practice" way - using product model \Magento\Catalog\Model\Product::addImageToMediaGallery

1. Copy the images from `import_dir` to `pub/media/tmp`
2. Add the images to the product
3. Save product

Code

    /* copy files from import_dir to pub/media/tmp */

    /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
    /* Init media gallery */
    $mediaGalleryEntries = $product->getMediaGalleryEntries();
    if (empty($mediaGalleryEntries) === true){
        $product->setMediaGalleryEntries([]);
    }

    /* Add an image to the product's gallery */
    $product->addImageToMediaGallery(
        $filePathFromTmpDir,
        [
          "image",
          "small_image",
          "thumbnail",
          "swatch_image" 
        ],
        $moveImage,
        $disableImage
    );

    /* Save */
    $this->_productRepository->save($product);

2. "Good practice" way - using API \Magento\Catalog\Api\ProductAttributeMediaGalleryManagementInterface::create

1. Create image content object via **\Magento\Framework\Api\Data\ImageContentInterfaceFactory**
2. Create image object via **\Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterfaceFactory**
3. Create an image via API

Code

    $imageContent = $this->_imageContentInterfaceFactory->create()
        ->setBase64EncodedData(base64_encode(file_get_contents($filePathImportDir)))
        ->setType($this->_mime->getMimeType($filePathImportDir))
        ->setName($file_name);

    $newImage = $this->_productAttributeMediaGalleryEntryInterfaceFactory->create()
        ->setMediaType(\Magento\Catalog\Model\Product\Attribute\Backend\Media\ImageEntryConverter::MEDIA_TYPE_CODE)
        ->setFile($filePathImportDir)
        ->setDisabled($disableImage)
        ->setContent($imageContent)
        ->setLabel('label');

    $this->_productAttributeMediaGalleryManagement->create($product->getSku(), $newImage);

Concerns:

  • In 1 I'm getting an error, which is known issue

    Undefined index: media_type

  • In 2 is way too complicated and it should be the easier way

Questions:

  • Is there "best practice" way to manage(add, remove, replace) product's images?
  • Maybe there is a way with \Magento\CatalogImportExport\Model\Import\Product
3

It can be done using your second way, more or less like this:

<?php


namespace [vendor]\[moduleName]\Model\Adminhtml\Product\MediaGallery;

use \Magento\Catalog\Model\Product\Gallery\EntryFactory;
use \Magento\Catalog\Model\Product\Gallery\GalleryManagement;
use \Magento\Framework\Api\ImageContentFactory;

{

/**
 * @var \Magento\Catalog\Model\Product\Gallery\EntryFactory
 */
private $mediaGalleryEntryFactory;


/**
 * @var \Magento\Catalog\Model\Product\Gallery\GalleryManagement
 */
private $mediaGalleryManagement;


/**
 * @var \Magento\Framework\Api\ImageContentFactory
 */
private $imageContentFactory;


/**
 * @param \Magento\Catalog\Model\Product\Gallery\EntryFactory $mediaGalleryEntryFactory
 * @param \Magento\Catalog\Model\Product\Gallery\GalleryManagement $mediaGalleryManagement
 * @param \Magento\Framework\Api\ImageContentFactory $imageContentFactory
 */
public function __construct
(
    EntryFactory $mediaGalleryEntryFactory,
    GalleryManagement $mediaGalleryManagement,
    ImageContentFactory $imageContentFactory
)
{
    $this->mediaGalleryEntryFactory = $mediaGalleryEntryFactory;
    $this->mediaGalleryManagement = $mediaGalleryManagement;
    $this->imageContentFactory = $imageContentFactory;
}


/**
 * @param string $filePath
 * @param string $sku
 */
public function processMediaGalleryEntry($filePath, $sku)
{
    $entry = $this->mediaGalleryEntryFactory->create();

    $entry->setFile($filePath);
    $entry->setMediaType('image');
    $entry->setDisabled(false);
    $entry->setTypes(['thumbnail', 'image', 'small_image']);

    $imageContent = $this->imageContentFactory->create();
    $imageContent
        ->setType(mime_content_type($filePath))
        ->setName('test')
        ->setBase64EncodedData(base64_encode(file_get_contents($filePath)));

    $entry->setContent($imageContent);

    $this->mediaGalleryManagement->create($sku, $entry);
}

}

$filePath should be an absolute path - maybe you can use constans BP.

  • it's sad that there is no more good ways to solve it, cuz as @JakubIlczuk said - it's highly limited. About this $entry->setMediaType('image'); line i'm not quite sure, cuz as far as i remember it caused me an error something like that it's need a type "png" or "jpg"(so in the end it should be "image/png"). But again, i'm not sure – Olga Zhe Jan 3 '17 at 6:33
  • In magento 2.1.1 it is no causing such an error. – Bartosz Kubicki Jan 3 '17 at 7:24
  • Neither method addresses remove or replace. Just an observation. – Rooster242 Sep 28 '17 at 5:41
0

after looking at the same things as You apparently I'm at exactly the same place, and can't find any better way then this 2. And this 2 are highly limited. In functional tests they are using simple product->save() thing which causes other problems (for me personally, url_key already exists error). Seems like only 2nd method can be used, however complicated and confusing it seems. But I wonder if in 2nd method you've found a way to set the uploaded images as thumbnail or small image?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.