Magento 2:從外部來源匯入產品

Magento 是一種電子商務解決方案,即其目的更多的是銷售產品,而不是伴隨銷售的倉儲、物流或財務會計。 其他應用程式(例如 ERP 系統)更適合隨附的應用程式。 因此,在使用 Magento 的實踐中,經常會出現將商店與這些其他系統(例如 1C)整合的任務。

總的來說,整合可以透過以下方式簡化為資料複製:

  • 目錄(產品、類別);
  • 庫存資料(倉庫中的產品餘額和價格);
  • 客戶;
  • 命令;

Magento 提供了一個單獨的物件類別來操作資料庫中的資料 - 儲存庫。 由於 Magento 的特殊性,透過儲存庫將資料添加到資料庫很容易編碼,但可以說很慢。 在本出版物中,我考慮了以「經典」方式以程式設計方式向 Magento 2 添加產品的主要階段 - 使用儲存庫類別。

客戶和訂單通常會從另一個方向複製 - 從 Magento 到外部 ERP 系統。 因此,使用它們更簡單,在 Magento 端你只需要選擇適當的數據,然後“子彈從我們身邊飛出“。

將資料記錄到資料庫的原理

目前,在 Magento 中以程式設計方式建立保存在資料庫中的物件是透過 工廠:

function __construct (MagentoCmsModelBlockFactory $blockFactory) {
    $this->blockFactory = $blockFactory;
}

/** @var MagentoCmsModelBlock $block */
$block = $this->blockFactory->create();

寫入資料庫是透過 知識庫:

function __construct (MagentoCmsApiBlockRepositoryInterface $blockRepo) {
    $this->blockRepo = $blockRepo;
}

$this->blockRepo->save($block);

「工廠」和「儲存庫」方法可用於 Magento 2 領域中的所有主要模型。

產品基本資訊

我正在尋找與 Magento 2.3 版本相符的資料結構。 本產品最基本的資訊見表 catalog_product_entity (產品註冊):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

我僅限於一種類型的產品(type_id='simple'),一組預設屬性(attribute_set_id=4) 並忽略屬性 has_options и required_options。 既然屬性 entity_id, created_at и updated_at 都是自動生成的,那麼,其實要增加一個新的產品,我們只需要設定 sku。 我這樣做:

/** @var MagentoCatalogApiDataProductInterfaceFactory $factProd */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
/** @var MagentoCatalogApiDataProductInterface $prod */
$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$repoProd->save($prod);

我得到一個例外:

The "Product Name" attribute value is empty. Set the attribute and try again.

我將產品名稱添加到請求中並收到一條訊息,指出缺少該屬性 Price。 添加價格後,產品將添加到資料庫中:

$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$prod->setName($name);
$prod->setPrice($price);
$repoProd->save($prod);

產品名稱儲存在產品 varchar 屬性表中(catalog_product_entity_varchar), 價格 - 表中 catalog_product_entity_decimal。 在新增產品之前,建議明確說明我們正在使用管理店面匯入資料:

/** @var MagentoStoreModelStoreManagerInterface $manStore */
$manStore->setCurrentStore(0);

附加屬性

使用 Magento 處理附加產品屬性是一種樂趣。 主要實體的EAV資料模型(見表 eav_entity_type)是該平台的主要功能之一。 我們只需將適當的屬性添加到產品模型中即可:

$prodEntity->setData('description', $desc);
$prodEntity->setData('short_description', $desc_short);
// или
$prodEntity->setDescription($desc);
$prodEntity->setShortDescription($desc_short);

透過 repo 物件保存模型時:

$repoProd->save($prod);

附加屬性也將儲存在對應的資料庫表中。

庫存數據

簡單來說 - 庫存產品的數量。 在 Magento 2.3 中,資料庫中描述儲存庫存資料格式的結構是 顯著不同 從之前發生的事情來看。 然而,透過產品模型添加產品的庫存數量並不比添加其他屬性困難多少:

/** @var MagentoCatalogModelProduct $prodEntity */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
$inventory = [
    'is_in_stock' => true,
    'qty' => 1234
];
$prodEntity->setData('quantity_and_stock_status', $inventory);
$repoProd->save($prodEntity);

媒體

通常,商店(電子商務)中客戶對產品的媒體支援與內部會計系統(ERP)中員工對相同產品的媒體支援不同。 在第一種情況下,建議面對面展示產品;在第二種情況下,給予產品的整體概念就足夠了。 然而,至少傳輸產品的主圖像是很常見的。 case 導入數據時。

透過管理面板新增影像時,影像首先保存在臨時目錄中(./pub/media/tmp/catalog/product)並且僅在儲存時將產品移至媒體目錄(./pub/media/catalog/product)。 此外,當透過管理面板新增時,影像會被標記 image, small_image, thumbnail, swatch_image.

/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
/** @var MagentoCatalogModelProductGalleryCreateHandler $hndlGalleryCreate */
/* $imagePath = '/path/to/file.png';  $imagePathRelative = '/f/i/file.png' */
$imagePathRelative = $this->imagePlaceToTmpMedia($imagePath);
/* reload product with gallery data */
$product = $repoProd->get($sku);
/* add image to product's gallery */
$gallery['images'][] = [
    'file' => $imagePathRelative,
    'media_type' => 'image'
    'label' => ''
];
$product->setData('media_gallery', $gallery);
/* set usage areas */
$product->setData('image', $imagePathRelative);
$product->setData('small_image', $imagePathRelative);
$product->setData('thumbnail', $imagePathRelative);
$product->setData('swatch_image', $imagePathRelative);
/* create product's gallery */
$hndlGalleryCreate->execute($product);

由於某種原因,僅在首次保存產品並再次從存儲庫檢索它後才鏈接媒體。 並且需要指定屬性 label 將條目新增至產品媒體庫時(否則我們會得到異常 Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

Категории

通常,商店的類別結構和後端應用程式或產品在其中的放置可能會有很大差異。 遷移有關類別和其中產品的資料的策略取決於許多因素。 在此範例中,我堅持以下原則:

  • 後端和商店類別透過名稱進行比較;
  • 如果匯入的類別不在商店中,則會在根類別下建立該類別(Default Category)且其在商店目錄中的進一步定位是手動假定的;
  • 只有當產品在商店中建立時(首次導入),產品才會被分配到類別;

此類別的基本資訊見表 catalog_category_entity (類別目錄)。 在 Magento 中建立類別:

/** @var MagentoCatalogApiDataCategoryInterfaceFactory $factCat */
/** @var MagentoCatalogApiCategoryRepositoryInterface $repoCat */
$cat = $factCat->create();
$cat->setName($name);
$cat->setIsActive(true);
$repoCat->save($cat);

使用類別 ID 和產品 SKU 將產品連結到類別:

/** @var MagentoCatalogModelCategoryProductLinkFactory $factCatProdLink */
/** @var MagentoCatalogApiCategoryLinkRepositoryInterface $repoCatLink */
$link = $factCatProdLink->create();
$link->setCategoryId($catMageId);
$link->setSku($prodSku);
$repoCatLink->save($link);

在總

編寫程式碼以程式設計方式將產品添加到 Magento 2 非常容易。 我已將上述所有內容合併到一個演示模組中“flancer32/mage2_ext_demo_import」。 模組中只有一個控制台命令 fl32:import:prod,導入 JSON 檔案中所描述的產品“./etc/data/products.json“:

[
  {
    "sku": "...",
    "name": "...",
    "desc": "...",
    "desc_short": "...",
    "price": ...,
    "qty": ...,
    "categories": ["..."],
    "image_path": "..."
  }
]

導入的圖片在目錄中 ./etc/data/img.

在我的筆記型電腦上,使用此方法匯入 10 個產品的時間約為 10 秒。 如果我們進一步發展這個想法,很容易得出這樣的結論:每小時大約可以導入3600個產品,導入100K個產品大約需要30個小時。 用伺服器替換筆記型電腦可以讓您在某種程度上緩解這種情況。 甚至可能有好幾次。 但不是幾個數量級。 或許這種快與慢在某種程度上就是這個專案出現的原因之一 magento/非同步導入.

提高導入速度的根本解決方案可能是直接輸入資料庫,但在這種情況下,所有有關 Magento 可擴展性的“好東西”都會丟失 - 您將必須自己“高級”地完成所有事情。 然而,這是值得的。 如果可行的話,我會在下一篇文章中考慮直接寫入資料庫的方法。

來源: www.habr.com

添加評論