Magento 2: importación de productos de fuentes externas

Magento es una solución de comercio electrónico, es decir más centrado en la venta de productos que en las ventas de almacén, logística o contabilidad financiera que lo acompañan. Otras aplicaciones (como los sistemas ERP) son más adecuadas para acompañantes. Por lo tanto, con bastante frecuencia en la práctica de usar Magento, surge la tarea de integrar una tienda con estos otros sistemas (por ejemplo, con 1C).


En general, la integración se puede reducir a la replicación de datos mediante:


  • catálogo (productos, categorías);
  • datos de inventario (existencias de productos en almacenes y precios);
  • a los clientes;
  • órdenes;

Magento para manipular datos en la base de datos ofrece una clase separada de objetos: repositorios . Debido a los detalles de Magento, agregar datos a la base de datos a través de repositorios es fácil de codificar, pero sucede, digamos, no rápidamente. En esta publicación, considero las etapas principales de agregar mediante programación un producto a Magento 2 de una manera "clásica", utilizando clases de repositorio.


Los clientes y pedidos generalmente se replican al otro lado, desde Magento hasta sistemas ERP externos. Por lo tanto, es más fácil con ellos, en el lado de Magento, solo necesita seleccionar los datos apropiados y luego " las balas disparadas desde nuestro lado ".


Principios de escritura de datos en la base de datos.


Por el momento, la creación de objetos almacenados en la base de datos mediante programación en Magento se realiza a través de Factory :


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

y escribiendo a la base de datos a través del Repositorio :


 function __construct (\Magento\Cms\Api\BlockRepositoryInterface $blockRepo) { $this->blockRepo = $blockRepo; } $this->blockRepo->save($block); 

El enfoque de Fábrica y Repositorio se puede utilizar para todos los modelos principales en el área temática de Magento 2.


Información básica del producto


Estoy considerando una estructura de datos correspondiente a Magento 2.3. La información más básica del producto se encuentra en la tabla catalog_product_entity (registro del producto):


 entity_id attribute_set_id type_id sku has_options required_options created_at updated_at 

Me type_id='simple' un tipo de producto ( type_id='simple' ), un conjunto de attribute_set_id=4 predeterminados ( attribute_set_id=4 ) e ignoro los atributos has_options y required_options . Dado que los atributos entity_id , created_at y updated_at se generan automáticamente, entonces, en esencia, solo necesitamos especificar sku para agregar un nuevo producto. Yo hago esto:


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

y obtén una excepción:


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

Agrego el nombre del producto a la solicitud y recibo un mensaje de que falta el atributo Price . Después de agregar el precio, el producto cae en la base de datos:


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

El nombre del producto se almacena en la tabla de atributos varchar del producto ( catalog_product_entity_varchar ), el precio se almacena en la tabla catalog_product_entity_decimal . Antes de agregar un producto, es aconsejable indicar explícitamente que estamos utilizando un escaparate administrativo para importar datos:


 /** @var \Magento\Store\Model\StoreManagerInterface $manStore */ $manStore->setCurrentStore(0); 

Atributos Adicionales


Procesar atributos de producto adicionales con Magento es un placer. El modelo de datos EAV para entidades centrales (consulte la tabla eav_entity_type ) es una de las características clave de esta plataforma. Simplemente agregue los atributos apropiados al modelo del producto:


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

y al guardar el modelo a través del objeto repo:


 $repoProd->save($prod); 

atributos adicionales también se almacenarán en las tablas de bases de datos correspondientes.


Datos de inventario


De una manera simple: la cantidad de producto en stock. En Magento 2.3, las estructuras de la base de datos que describen el formato para almacenar datos de inventario son significativamente diferentes de lo que eran antes. Sin embargo, agregar cantidades de productos en stock a través de un modelo de producto no es mucho más difícil que agregar otros atributos:


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

Medios de comunicación


Como regla general, el soporte de medios para un producto para un cliente en una tienda (comercio electrónico) es diferente del soporte de medios para el mismo producto para un empleado en un sistema de contabilidad interno (ERP). En el primer caso, es deseable mostrar la "cara del producto", en el segundo, es suficiente para dar una idea general del producto. Sin embargo, la transferencia de al menos la imagen principal del producto es un case bastante común al importar datos.


Al agregar una imagen a través del panel de administración, la imagen se guarda primero en el directorio temporal ( ./pub/media/tmp/catalog/product ) y solo cuando el producto se guarda se mueve al directorio de medios ( ./pub/media/catalog/product ). Además, cuando se agrega a través del small_image administración, la imagen se establece en las swatch_image image , small_image , thumbnail , swatch_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); 

Por alguna razón, los medios están atados solo después de guardar el producto preliminarmente y recibirlo nuevamente desde el repositorio. Y debe especificar el atributo de label al agregar una entrada a la galería de medios del producto (de lo contrario, obtenemos la excepción de Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516 ).


Categorias


A menudo, la estructura de las categorías de la tienda y las aplicaciones de back-end o la colocación de productos en ellas puede variar significativamente. Las estrategias para transferir datos sobre categorías y productos en ellas dependen de muchos factores. En este ejemplo, me limito a lo siguiente:


  • las categorías de backend y tienda se comparan por nombre;
  • si se importa una categoría que no está en la tienda, se crea bajo la categoría raíz ( Default Category ) y se asume su posterior posicionamiento en el catálogo de la tienda manualmente;
  • un producto se asigna a una categoría solo cuando se crea en una tienda (primera importación);

La información básica de la categoría se encuentra en la tabla catalog_category_entity (catálogo de categorías). Crear una categoría en 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); 

El producto se asigna a una categoría por ID de categoría y SKU del producto:


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

Total


Escribir código para agregar un producto a Magento 2 mediante programación es muy fácil. Todo lo anterior, lo he reducido al módulo de demostración " flancer32 / mage2_ext_demo_import ". Solo hay un fl32:import:prod console en el fl32:import:prod , que importa los productos descritos en el archivo JSON " ./etc/data/products.json ":


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

Las imágenes para importar se encuentran en el directorio ./etc/data/img .


El tiempo de importación de 10 productos de esta manera es de aproximadamente 10 segundos en mi computadora portátil. Si desarrollamos más esta idea, es fácil concluir que se pueden importar alrededor de 3.600 productos por hora, y se pueden tomar alrededor de 30 horas para importar 100K productos. Reemplazar una computadora portátil con un servidor le permite suavizar la situación. Quizás incluso a veces. Pero no por órdenes de magnitud. Tal vez esto velocidad la lentitud es, en cierta medida, una de las razones del surgimiento del proyecto magento / async-import .


Una decisión fundamental para aumentar la velocidad de importación puede ser escribir directamente en la base de datos, pero en este caso se pierden todos los "bollos" con respecto a la extensibilidad de Magento: debe hacer todo "avanzado" usted mismo. Sin embargo, vale la pena. Si funciona, consideraré el enfoque con grabación directa en la base de datos en el próximo artículo.

Source: https://habr.com/ru/post/es436020/


All Articles