Magento 2 - это более быстрый способ программного изменения записей в галерее товаров

8

Мне нужно сделать огромное обновление данных о продукте, но то, что мне нужно сделать, не может быть достигнуто с помощью импорта продукта. Например, мне нужно обновить медиа-галерею и категории для определенных продуктов, но решение, которое я предложил, занимает слишком много времени.

Небольшое резюме: я добавил команду в CLI Magento 2, которая, учитывая файл конфигурации 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метода, который быстрее сохраняет связь категории / продукта, чем полное сохранение продукта)

CaNNaDaRk
источник

Ответы:

0

Я думаю, что вы на правильном пути: сохранение продукта занимает много времени и нужно идти ..

Теперь, с обновлением изображений, это может быть действительно сложно. Но я хотел бы думать, что это может быть путь вперед, чтобы отделить проблему:

  • я предполагаю, что вам нужно, чтобы данные мультимедиа были сохранены в базе данных, и это можно сделать с помощью вашего метода saveAttribute .. (очень быстро). Однако, вы можете добавить некоторые атрибуты в ваш скрипт обновления: см. Атрибуты 'image, small_image, thumbnail' (см. В базе данных select * from eav_attribute where ((attribute_code like '%image%') or (attribute_code='thumbnail')) and entity_type_id=4))

  • Теперь более сложным, но все же у меня могут быть некоторые идеи, это иметь дело с изображением, говоря физически, и возможными дополнительными данными мультимедиа (заголовок тега изображения, положение и т. д.)

-> для этого второго пункта: я бы посмотрел на класс Magento \ Catalogue \ 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()));
    }

Сохраняет довольно быстро. Я могу запустить 10000 продуктов в течение нескольких минут. Это включает в себя поиск носителя, который называется {sku} .jpg, и все они помещены в одну папку.

djfordz
источник
Можно ли просто установить роли изображения, т.е. -> setTypes (['thumbnail', 'small_image', 'image']) без замены всего изображения?
Пай