Magento 2:从外部来源导入产品

Magento是一种电子商务解决方案,即 与销售伴随的仓库,物流或财务会计相比,更注重产品的销售。 其他应用程序(例如ERP系统)更适合于同伴。 因此,在使用Magento的实践中,经常会出现将商店与其他系统(例如1C)集成的任务。


总的来说,可以通过以下方式将集成简化为数据复制:


  • 目录(产品,类别);
  • 库存数据(仓库中产品的库存和价格);
  • 给客户;
  • 订单;

Magento用于处理数据库中的数据,提供了单独的一类对象- 存储库 。 由于Magento的特殊性,通过存储库将数据添加到数据库很容易编写代码,但是这种情况发生的速度并不快。 在本出版物中,我考虑了使用回购类以“经典”方式以编程方式将产品添加到Magento 2的主要阶段。


客户和订单通常复制到另一端-从Magento到外部ERP系统。 因此,使用它们比较容易,在Magento方面,您只需要选择适当的数据,然后选择“ 从我们方发射的子弹 ”即可。


将数据写入数据库的原理


目前,通过Magento以编程方式在数据库中存储对象的创建是通过Factory完成的:


function __construct (\Magento\Cms\Model\BlockFactory $blockFactory) { $this->blockFactory = $blockFactory; } /** @var \Magento\Cms\Model\Block $block */ $block = $this->blockFactory->create(); 

并通过存储库写入数据库:


 function __construct (\Magento\Cms\Api\BlockRepositoryInterface $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'限制type_id='simple'一种类型的产品( type_id='simple' ),一组默认attribute_set_id=4attribute_set_id=4 ),而忽略has_optionsrequired_options属性。 由于entity_idcreated_atupdated_at属性是自动生成的,因此,实质上,我们只需要指定sku即可添加新产品。 我这样做:


 /** @var \Magento\Catalog\Api\Data\ProductInterfaceFactory $factProd */ /** @var \Magento\Catalog\Api\ProductRepositoryInterface $repoProd */ /** @var \Magento\Catalog\Api\Data\ProductInterface $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 \Magento\Store\Model\StoreManagerInterface $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); 

通过回购对象保存模型时:


 $repoProd->save($prod); 

其他属性也将存储在相应的数据库表中。


库存数据


简单来说,就是库存产品的数量。 在Magento 2.3中,描述存储库存数据格式的数据库结构与以前大不相同 。 但是,通过产品模型添加库存中的产品数量并不比添加其他属性难得多:


 /** @var \Magento\Catalog\Model\Product $prodEntity */ /** @var \Magento\Catalog\Api\ProductRepositoryInterface $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 )。 另外,通过管理small_image添加时,图像会设置为imagesmall_imagethumbnailswatch_image


 /** @var \Magento\Catalog\Api\ProductRepositoryInterface $repoProd */ /** @var \Magento\Catalog\Model\Product\Gallery\CreateHandler $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获得Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516异常Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516 )。


分类目录


通常,商店类别和后端应用程序的结构或产品在其中的位置可能会有很大不同。 有关类别和产品中的数据的传输策略取决于许多因素。 在此示例中,我坚持以下几点:


  • 后端和存储类别按名称进行比较;
  • 如果导入的类别不在商店中,则在根类别( Default Category )下创建该类别,并手动假定其在商店目录中的位置;
  • 仅当在商店中创建产品时(第一次导入),才将产品分配给类别;

基本类别信息在catalog_category_entity表(类别目录)中。 在Magento中创建类别:


 /** @var \Magento\Catalog\Api\Data\CategoryInterfaceFactory $factCat */ /** @var \Magento\Catalog\Api\CategoryRepositoryInterface $repoCat */ $cat = $factCat->create(); $cat->setName($name); $cat->setIsActive(true); $repoCat->save($cat); 

通过类别ID和产品SKU将产品分配给类别:


 /** @var \Magento\Catalog\Model\CategoryProductLinkFactory $factCatProdLink */ /** @var \Magento\Catalog\Api\CategoryLinkRepositoryInterface $repoCatLink */ $link = $factCatProdLink->create(); $link->setCategoryId($catMageId); $link->setSku($prodSku); $repoCatLink->save($link); 

合计


编写代码以编程方式将产品添加到Magento 2非常容易。 以上所有内容,我都简化为演示模块“ flancer32 / mage2_ext_demo_import ”。 模块中只有一个fl32:import:prod console命令,该命令将导入“ ./etc/data/products.json ” JSON文件中描述的产品:


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

要导入的图片位于./etc/data/img目录中。


以这种方式导入10种产品的时间在我的笔记本电脑上约为10秒。 如果我们进一步发展这个想法,很容易得出结论,每小时可以进口大约3600种产品,而进口10万种产品大约需要30个小时。 用服务器代替笔记本电脑可以使您的情况有所缓解。 甚至有时。 但不是数量级。 也许这个 速度 速度缓慢在某种程度上是magento / async-import项目出现的原因之一。


提高导入速度的主要决定可能是直接写入数据库,但是在这种情况下,所有与Magento可扩展性有关的“小麻烦”都丢失了-您必须自己“做”高级的事情。 但是,这是值得的。 如果解决了,那么在下一篇文章中,我将考虑在数据库中直接记录的方法。

Source: https://habr.com/ru/post/zh-CN436020/


All Articles