Magento 2 est un moyen plus rapide de modifier par programmation les entrées de la galerie multimédia du produit

8

J'ai besoin de faire une mise à jour massive des données produit, mais ce que je dois faire ne peut pas être réalisé avec l'importation de produits. Par exemple, je dois mettre à jour la galerie de médias et les catégories pour des produits donnés, mais la solution avec laquelle je suis sorti prend trop de temps.

Un petit récapitulatif: j'ai ajouté une commande à la CLI Magento 2 qui, étant donné un fichier de configuration json, supprime, ajoute, met à jour ou trie les entrées de la galerie multimédia pour un produit donné comme celui-ci. Ici, je colle un extrait du code:

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

Puisqu'il s'agit d'une mise à jour massive, la ligne «$ product-> save ()» est appelée plusieurs fois et prend toujours de 2 à 4 secondes. Étant donné que je dois lancer le code de milliers de produits, j'ai besoin d'un moyen plus rapide de le faire.

J'ai essayé avec

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

et

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

mais cela ne fonctionne pas pour la galerie multimédia (ne fonctionne que pour eav je pense).

Existe-t-il un moyen de sauvegarder uniquement la galerie multimédia et de conserver ces modifications plus rapidement?

(Ce que je recherche est quelque chose comme une Magento\Catalog\Api\CategoryLinkManagementInterface::assignProductToCategoriesméthode qui enregistre l'association catégorie / produit plus rapidement qu'une sauvegarde complète du produit)

CaNNaDaRk
la source

Réponses:

0

Je pense que vous êtes sur la bonne voie: le produit de sauvegarde prend du temps et doit disparaître.

Maintenant, avec la mise à jour des images, cela peut être vraiment délicat. Mais j'aimerais penser que ce pourrait être une façon d'avancer pour séparer le problème:

  • je suppose que vous avez besoin que les données multimédias soient stockées dans la base de données et cela peut être fait en utilisant votre méthode saveAttribute .. (très rapide). Cependant, vous voudrez peut-être ajouter certains attributs dans votre script de mise à jour: voir les attributs 'image, small_image, thumbnail' (voir dans la base de données select * from eav_attribute where ((attribute_code like '%image%') or (attribute_code='thumbnail')) and entity_type_id=4))

  • maintenant le plus complexe mais j'ai peut-être quelques idées, c'est de traiter physiquement l'image et d'éventuelles données média supplémentaires (titre de la balise image, position, etc.)

-> pour ce deuxième point: je regarderais la classe Magento \ Catalog \ Model \ Product \ Gallery \ CreateHandler car elle vous montrera comment Magento fait tout fonctionner en ce qui concerne les données multimédias.

Hervé Tribouilloy
la source
0

Pour autant que je sache, il n'y a aucun moyen de sauvegarder des entrées multimédias sans enregistrer le produit. mais le produit de sauvegarde ne devrait pas prendre très longtemps avec le productRepositoryInterface.

J'ai créé un module similaire et je n'ai pas le même problème avec la sauvegarde multimédia.

Voici ma solution pour sauvegarder des médias:

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

J'enregistre ensuite le produit avec 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()));
    }

Il enregistre assez rapidement. Je peux exécuter 10 000 produits en quelques minutes. Cela inclut la recherche du média nommé {sku} .jpg et le tout dans un seul dossier.

djfordz
la source
est-il possible de définir simplement les rôles d'image, c'est-à-dire -> setTypes (['miniature', 'petite_image', 'image']) sans remplacer l'image entière?
paj