Magento 2は、製品のメディアギャラリーのエントリをプログラムで変更するためのより高速な方法です。


8

製品データの大規模な更新を行う必要がありますが、実行する必要のあることは、製品のインポートでは実現できません。例では、特定の製品のメディアギャラリーとカテゴリを更新する必要がありますが、私が思いついたソリューションには時間がかかりすぎます。

簡単にまとめます。Magento2 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、完全な製品の保存よりも速くカテゴリ/製品の関連付けを保存する方法のようなものです)

回答:


0

私はあなたが正しい軌道に乗っていると思います:セーブプロダクトは時間がかかり、行く必要があります。

さて、画像を更新すると、それは本当にトリッキーになる可能性があります。しかし、私はそれが問題を分離するための前向きな方法かもしれないと考えたいのです。

  • 私の推測では、メディアデータをデータベースに保存する必要があります。これは、saveAttribute ..メソッドを使用して実行できます(非常に高速)。ただし、更新スクリプトにいくつかの属性を追加することをお勧めします。属性 'image、small_image、thumbnail'を参照してください(データベースを参照 select * from eav_attribute where ((attribute_code like '%image%') or (attribute_code='thumbnail')) and entity_type_id=4)

  • 今はもっと複雑ですが、私はいくつかのアイデアを持っているかもしれませんが、物理的に話す画像と可能な追加のメディアデータ(画像タグのタイトル、位置など)を処理することです

->この2番目の点について:Magentoがメディアデータに関してすべての機能を維持する方法を示すため、Magento \ Catalog \ Model \ Product \ Gallery \ CreateHandlerクラスを確認します。


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という名前のメディアを検索し、すべてを1つのフォルダーに詰め込みます。


画像全体を置き換えることなく、単に画像の役割を設定することは可能ですか?-> setTypes(['thumbnail'、 'small_image'、 'image'])?
PAJ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.