Magento es una solución de comercio electrónico, es decir. está más orientado a la venta de productos que al almacenamiento, la logística o la contabilidad financiera que acompaña a las ventas. Otras aplicaciones (por ejemplo, los sistemas ERP) son más adecuadas para aplicaciones complementarias. Por lo tanto, muy a menudo en la práctica de utilizar Magento surge la tarea de integrar una tienda con estos otros sistemas (por ejemplo, 1C).
En general, la integración se puede reducir a la replicación de datos mediante:
- catálogo (productos, categorías);
- datos de inventario (saldos de productos en almacenes y precios);
- clientela;
- pedidos;
Magento ofrece una clase separada de objetos para manipular datos en la base de datos:
Los clientes y los pedidos normalmente se replican en la otra dirección: desde Magento a sistemas ERP externos. Por lo tanto, es más sencillo con ellos, en el lado de Magento solo necesitas seleccionar los datos apropiados y luego "Las balas salieron volando de nuestro lado.«.
Principios para registrar datos en una base de datos.
Por el momento, la creación de objetos guardados en la base de datos mediante programación en Magento se realiza a través de
function __construct (MagentoCmsModelBlockFactory $blockFactory) {
$this->blockFactory = $blockFactory;
}
/** @var MagentoCmsModelBlock $block */
$block = $this->blockFactory->create();
y la escritura en la base de datos se realiza a través de
function __construct (MagentoCmsApiBlockRepositoryInterface $blockRepo) {
$this->blockRepo = $blockRepo;
}
$this->blockRepo->save($block);
El enfoque "Fábrica" y "Repositorio" se puede utilizar para todos los modelos principales en el dominio Magento 2.
Información básica del producto
Estoy viendo una estructura de datos que coincide con la versión Magento 2.3. La información más básica sobre el producto se encuentra en la tabla. catalog_product_entity
(registro de producto):
entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at
Estoy limitado a un tipo de producto (type_id='simple'
), un conjunto de atributos predeterminados (attribute_set_id=4
) e ignorar los atributos has_options
и required_options
. Dado que los atributos entity_id
, created_at
и updated_at
se generan automáticamente, entonces, de hecho, para agregar un nuevo producto, solo necesitamos configurar sku
. Hago esto:
/** @var MagentoCatalogApiDataProductInterfaceFactory $factProd */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
/** @var MagentoCatalogApiDataProductInterface $prod */
$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$repoProd->save($prod);
y me sale 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 aparece un mensaje que indica que falta el atributo Price
. Luego de agregar el precio, el producto se agrega a 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
), precio - en la tabla catalog_product_entity_decimal
. Antes de agregar un producto, es recomendable indicar explícitamente que estamos utilizando el escaparate administrativo para importar datos:
/** @var MagentoStoreModelStoreManagerInterface $manStore */
$manStore->setCurrentStore(0);
Atributos adicionales
Procesar atributos adicionales del producto usando Magento es un placer. Modelo de datos EAV para entidades principales (ver tabla eav_entity_type
) es una de las características clave de esta plataforma. Simplemente agregamos los atributos apropiados al modelo de 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 de repositorio:
$repoProd->save($prod);
Los atributos adicionales también se almacenarán en las tablas de la base de datos correspondientes.
datos de inventario
En términos simples: la cantidad de producto en stock. En Magento 2.3, las estructuras en la base de datos que describen el formato para almacenar datos de inventario son
/** @var MagentoCatalogModelProduct $prodEntity */
/** @var MagentoCatalogApiProductRepositoryInterface $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 mediático de un producto para un cliente en una tienda (comercio electrónico) difiere del soporte mediático del mismo producto para un empleado en un sistema de contabilidad interno (ERP). En el primer caso es recomendable mostrar el producto cara a cara, en el segundo basta con dar una idea general del producto. Sin embargo, transferir al menos la imagen principal de un producto es bastante común. case
al importar datos.
Al agregar una imagen a través del panel de administración, la imagen primero se guarda en un directorio temporal (./pub/media/tmp/catalog/product
) y solo cuando se guarda el producto se mueve al directorio de medios (./pub/media/catalog/product
). Además, cuando se agrega a través del panel de administración, la imagen se etiqueta 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);
Por alguna razón, los medios se vinculan solo después de guardar el producto y recuperarlo nuevamente del repositorio. Y necesitas especificar el atributo. label
al agregar una entrada a la galería de medios del producto (de lo contrario, obtenemos una excepción Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516
).
categoría
A menudo, la estructura de categorías de la tienda y la aplicación backend o la ubicación de los productos en ellas pueden diferir significativamente. Las estrategias para migrar datos sobre categorías y productos dentro de ellas dependen de muchos factores. En este ejemplo me quedo con 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 en la categoría raíz (
Default Category
) y su posterior posicionamiento en el catálogo de la tienda se asume manualmente; - un producto se asigna a una categoría solo cuando se crea en la tienda (primera importación);
La información básica sobre la categoría está en la tabla. catalog_category_entity
(catálogo de categorías). Creando una categoría en Magento:
/** @var MagentoCatalogApiDataCategoryInterfaceFactory $factCat */
/** @var MagentoCatalogApiCategoryRepositoryInterface $repoCat */
$cat = $factCat->create();
$cat->setName($name);
$cat->setIsActive(true);
$repoCat->save($cat);
La vinculación de un producto a una categoría se realiza mediante el ID de categoría y el SKU del producto:
/** @var MagentoCatalogModelCategoryProductLinkFactory $factCatProdLink */
/** @var MagentoCatalogApiCategoryLinkRepositoryInterface $repoCatLink */
$link = $factCatProdLink->create();
$link->setCategoryId($catMageId);
$link->setSku($prodSku);
$repoCatLink->save($link);
En total
Escribir código para agregar un producto mediante programación a Magento 2 es bastante fácil. He combinado todo lo indicado anteriormente en un módulo de demostración "fl32:import:prod
, que importa los productos descritos en el archivo JSON "
[
{
"sku": "...",
"name": "...",
"desc": "...",
"desc_short": "...",
"price": ...,
"qty": ...,
"categories": ["..."],
"image_path": "..."
}
]
Las fotos para importar están en el catálogo. ./etc/data/img
.
El tiempo para importar 10 productos usando este método es de aproximadamente 10 segundos en mi computadora portátil. Si desarrollamos más esta idea, es fácil llegar a la conclusión de que se pueden importar alrededor de 3600 productos por hora, y que se pueden necesitar unas 100 horas para importar 30 productos. Reemplazar una computadora portátil con un servidor le permite suavizar un poco la situación. Quizás incluso varias veces. Pero no por órdenes de magnitud. Quizás esta velocidad y lentitud sea, en cierta medida, una de las razones del surgimiento del proyecto.
Una solución radical para aumentar la velocidad de importación podría ser la entrada directa a la base de datos, pero en este caso se pierden todos los "beneficios" relacionados con la extensibilidad de Magento: todo lo "avanzado" tendrá que hacerlo usted mismo. Sin embargo, vale la pena. Si funciona, consideraré el enfoque con escritura directa en la base de datos en el próximo artículo.
Fuente: habr.com