Mit Magento 2 können Produktmediengalerieeinträge schneller programmgesteuert geändert werden

8

Ich muss die Produktdaten massiv aktualisieren, aber was ich tun muss, kann mit dem Produktimport nicht erreicht werden. Zum Beispiel muss ich die Mediengalerie und Kategorien für bestimmte Produkte aktualisieren, aber die Lösung, die ich herausgebracht habe, dauert zu lange.

Ein kleiner Rückblick: Ich habe der Magento 2-CLI einen Befehl hinzugefügt, der anhand einer JSON-Konfigurationsdatei Mediengalerieeinträge für ein bestimmtes Produkt wie dieses entfernt, hinzufügt, aktualisiert oder sortiert. Hier füge ich einen Auszug aus dem Code ein:

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

Da es sich um ein umfangreiches Update handelt, wird die Zeile "$ product-> save ()" mehrmals aufgerufen und dauert immer 2 bis 4 Sekunden. Da ich den Code für Tausende von Produkten starten muss, brauche ich einen schnelleren Weg, dies zu tun.

Ich habe es mit versucht

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

und

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

Aber das funktioniert nicht für Mediengalerien (funktioniert nur für EA, denke ich).

Gibt es eine Möglichkeit, nur die Mediengalerie zu speichern und diese Änderungen schneller beizubehalten?

(Was ich suche, ist so etwas wie eine Magento\Catalog\Api\CategoryLinkManagementInterface::assignProductToCategoriesMethode, die die Kategorie- / Produktzuordnung schneller speichert als eine vollständige Produktspeicherung)

CaNNaDaRk
quelle

Antworten:

0

Ich denke, Sie sind auf dem richtigen Weg: Das sichere Produkt dauert lange und muss gehen.

Mit der Aktualisierung der Bilder kann das sehr schwierig sein. Aber ich würde gerne denken, dass es ein Weg sein könnte, das Problem zu trennen:

  • Ich vermute, Sie müssen die Mediendaten in der Datenbank speichern, und das kann mit Ihrer Methode saveAttribute .. (sehr schnell) erfolgen. Möglicherweise möchten Sie Ihrem Aktualisierungsskript jedoch einige Attribute hinzufügen: siehe Attribute 'image, small_image, thumbnail' (siehe in der Datenbank select * from eav_attribute where ((attribute_code like '%image%') or (attribute_code='thumbnail')) and entity_type_id=4))

  • Jetzt ist es komplexer, aber ich habe vielleicht einige Ideen, mich physisch mit dem Bild und möglichen zusätzlichen Mediendaten (Titel des Bild-Tags, Position usw.) zu befassen.

-> für diesen zweiten Punkt: Ich würde mir die Klasse Magento \ Catalog \ Model \ Product \ Gallery \ CreateHandler ansehen, da sie Ihnen zeigt, wie Magento alles in Bezug auf die Mediendaten funktioniert.

Herve Tribouilloy
quelle
0

Soweit ich weiß, gibt es keine Möglichkeit, Medieneinträge zu speichern, ohne das Produkt zu speichern. Das Speichern des Produkts sollte mit dem productRepositoryInterface jedoch nicht lange dauern.

Ich habe ein ähnliches Modul erstellt und habe nicht das gleiche Problem beim Speichern von Medien.

Hier ist meine Lösung zum Speichern von Medien:

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

Ich speichere das Produkt dann mit dem 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()));
    }

Es spart ziemlich schnell. Ich kann innerhalb weniger Minuten 10.000 Produkte ausführen. Dazu gehört die Suche nach Medien, die als {sku} .jpg bezeichnet werden und alle in einem einzigen Ordner gespeichert sind.

djfordz
quelle
Ist es möglich, nur Bildrollen festzulegen, dh -> setTypes (['thumbnail', 'small_image', 'image']), ohne das gesamte Bild zu ersetzen?
paj