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 这两款产品都非常容易编程。我已经把上面描述的所有内容都整合到一个演示模块中。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 ——所有“高级”操作都得我自己来做。不过,这很值得。如果一切顺利,我会在下一篇文章中探讨直接写入数据库的方法。

来源: habr.com

为具有 DDoS 保护、VPS VDS 服务器的站点购买可靠的主机 🔥 购买具备 DDoS 防护的可靠网站托管服务,包括 VPS 和 VDS 服务器 | ProHoster