Magento 2 existe uma maneira mais rápida de alterar as entradas da galeria de mídia do produto programaticamente


8

Preciso fazer uma atualização maciça dos dados do produto, mas o que preciso fazer não pode ser alcançado com a importação do produto. No exemplo, preciso atualizar a galeria de mídia e as categorias de determinados produtos, mas a solução que eu criei leva muito tempo.

Um pequeno resumo: adicionei um comando ao Magento 2 CLI que, dado um arquivo de configuração json, remove, adiciona, atualiza ou classifica as entradas da galeria de mídia para um determinado produto como este. Aqui colo um trecho do código:

/* $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();

Como é uma atualização maciça, a linha "$ product-> save ()" é chamada muitas vezes e sempre leva de 2 a 4 segundos. Como preciso lançar o código para milhares de produtos, preciso de uma maneira mais rápida de fazer isso.

Eu tentei com

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

e

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

mas isso não funciona para a galeria de mídia (só funciona para eav, eu acho).

Existe uma maneira de salvar apenas a galeria de mídia e persistir com essas alterações mais rapidamente?

O que procuro é algo como um Magento\Catalog\Api\CategoryLinkManagementInterface::assignProductToCategoriesmétodo que salva a associação de categoria / produto mais rapidamente do que uma economia completa do produto.

Respostas:


0

Acho que você está no caminho certo: o produto salvo está demorando muito e precisa ir embora.

Agora, com a atualização de imagens, isso pode ser realmente complicado. Mas gostaria de pensar que pode ser um caminho a seguir para separar o problema:

  • Meu palpite é que você precisa que os dados de mídia sejam armazenados no banco de dados e isso pode ser feito usando o método saveAttribute .. (muito rápido). No entanto, convém adicionar alguns atributos ao seu script de atualização: consulte a imagem dos atributos, imagem pequena, imagem em miniatura (consulte no banco de dados select * from eav_attribute where ((attribute_code like '%image%') or (attribute_code='thumbnail')) and entity_type_id=4))

  • agora, o mais complexo, mas ainda assim posso ter algumas idéias, é lidar com a imagem fisicamente falando e com possíveis dados extras de mídia (título da etiqueta da imagem, posição e assim por diante)

-> para este segundo ponto: eu examinaria a classe Magento \ Catálogo \ Modelo \ Produto \ Galeria \ CreateHandler, pois ela mostrará como o Magento mantém tudo funcionando com relação aos dados de mídia.


0

Tanto quanto sei, não há como salvar entradas de mídia sem salvar o produto. mas o produto salvo não deve demorar muito com o productRepositoryInterface.

Criei um módulo semelhante e não tenho o mesmo problema com o salvamento de mídia.

Aqui está minha solução para salvar mídia:

 /**
     * 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;
    }

Em seguida, salve o produto com o 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()));
    }

Economiza muito rapidamente. Posso executar 10.000 produtos em alguns minutos. Isso inclui a pesquisa da mídia nomeada como {sku} .jpg e tudo em uma única pasta.


é possível apenas definir funções de imagem, ou seja, -> setTypes (['thumbnail', 'small_image', 'image']) sem substituir a imagem inteira?
paj
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.