Magento 2提供了一种更快的方式以编程方式更改产品媒体库条目


8

我需要对产品数据进行大量更新,但是产品导入无法实现我需要做的事情。例如,我需要更新给定产品的媒体库和类别,但是我提出的解决方案花费的时间太长。

简要回顾一下:我在Magento 2 CLI中添加了一个命令,给定json配置文件,该命令可以为这样的给定产品删除,添加,更新或排序媒体库条目。在这里粘贴代码摘录:

/* $product is of type Magento\Catalog\Model\Product */

//get existing media gallery
$existingMediaGallery = $product->getMediaGallery();

/* 
   do stuff with media gallery (alter $existingMediaGallery)
   (add, remove, sort, ...)
*/

//set media gallery again
$product->setMediaGallery($existingMediaGallery);

//process media gallery
$mediaGalleryEntries = $product->getMediaGalleryEntries();
$this->getMediaGalleryProcessor()->clearMediaAttribute($product, array_keys($product->getMediaAttributes()));
if ($mediaGalleryEntries) {
  foreach ($mediaGalleryEntries as $k => $entry) {
    if (!isset($entry['removed']) && !empty($entry['types'])) {
      $this->getMediaGalleryProcessor()->setMediaAttribute($product, $entry['types'], $entry['file']);
    }
  }
}

//save product
$product->save();

由于这是一次大规模的更新,因此“ $ product-> save()”这一行被多次调用,并且通常需要2到4秒。由于我需要启动数千种产品的代码,因此需要一种更快的方法。

我尝试过

$product->getResource()->saveAttribute($product, 'media_gallery');

$product->addAttributeUpdate('media_gallery', $mediaGallery, $storeId);

但这不适用于媒体库(我认为仅适用于eav)。

有没有办法只保存媒体库并更快地保留这些更改?

(我要寻找的是一种类似Magento\Catalog\Api\CategoryLinkManagementInterface::assignProductToCategories方法,该方法比完全保存产品更快地保存类别/产品关联)

Answers:


0

我认为您走的路是正确的:保存产品需要很长时间,需要继续..

现在,随着图像更新,这可能真的很棘手。但我想这可能是解决问题的一种方法:

  • 我的猜测是您需要将媒体数据存储在数据库中,并且可以通过使用方法saveAttribute ..(非常快)来完成。但是,您可能需要在更新脚本中添加一些属性:请参见属性“图像,small_image,缩略图”(请参见数据库 select * from eav_attribute where ((attribute_code like '%image%') or (attribute_code='thumbnail')) and entity_type_id=4))。

  • 现在比较复杂,但我可能还有一些想法,就是要从物理角度处理图像以及可能的额外媒体数据(图像标签标题,位置等)

->关于第二点:我将看一看Magento \ Catalog \ Model \ Product \ Gallery \ CreateHandler类,因为它将向您展示Magento如何使所有媒体数据保持正常工作。


0

据我所知,没有一种方法可以保存媒体条目而不保存产品。但是使用productRepositoryInterface,保存产品根本不需要花费很长时间。

我创建了一个类似的模块,但是媒体保存没有相同的问题。

这是我保存媒体的解决方案:

 /**
     * Add Product media from folder.
     * @param $product
     * @param $productData
     * @return mixed
     */
    protected function setProductMedia($product, $productData)
    {
        $medias = [];
        $files = scandir(self::MEDIA_PATH);
        $mediaPath = '';
        foreach ($files as $file) {
            if ($file !== '.' && $file !== '..') {
                $path = realpath(self::MEDIA_PATH . $file);
                if ($path) {
                    if (basename($path, '.jpg') == trim($productData['productCode'])) {
                        $mediaPath = self::MEDIA_PATH . $file;
                        break;
                    }
                }
            }
        }

        if ((bool)$mediaPath) {
            $image = $this->_imageContent
               ->setBase64EncodedData(base64_encode(file_get_contents($mediaPath)))
               ->setType(image_type_to_mime_type(exif_imagetype($mediaPath)))
               ->setName(basename($mediaPath));

            $media = $this->_productAttributeMediaGalleryEntry
               ->setFile($mediaPath)
               ->setTypes(['thumbnail', 'small_image', 'image'])
               ->setLabel($productData['description'])
               ->setPosition(0)
               ->setMediaType('image')
               ->setContent($image)
               ->setDisabled(false)
               ->setPosition(0);

            $medias[] = $media;
            $product->setMediaGalleryEntries($medias);
       }

        return $product;
    }

然后,我将产品与productRepositoryInterface保存在一起。

   try {
        $product = $this->_productRepository->get($productData['productCode']);
    } catch (NoSuchEntityException $e) {
        throw new NoSuchEntityException(__('Could Not Update Product Error: %1', $e->getMessage()));
    }

    $product = $this->setProductMedia($product, $productData);

    try {
       $this->_productRepository->save($product);
    } catch (InputException $exception) {
       $this->_logger->critical(__("Could not save product Error: %1", $exception->getMessage()));
    } catch (StateException $exception) {
       $this->_logger->critical(__("Could not save product, Error: %1",$exception->getMessage()));
    } catch (CouldNotSaveException $exception) {
       $this->_logger->critical(__('Could Not Save Product Error: %1' ,$exception->getMessage()));
    }

它节省得很快。我可以在几分钟内运行10,000个产品。其中包括搜索名为{sku} .jpg的媒体并将所有媒体都填充在一个文件夹中。


是否可以仅设置图像角色,即-> setTypes(['thumbnail','small_image','image'])而不替换整个图像?
paj
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.