Magento é uma solução de e-commerce, ou seja, visa mais a venda de produtos do que a armazenagem, a logística ou a contabilidade financeira que acompanha as vendas. Outras aplicações (por exemplo, sistemas ERP) são mais adequadas para acompanhar aplicações. Portanto, muitas vezes na prática de utilização do Magento surge a tarefa de integrar uma loja com esses outros sistemas (por exemplo, 1C).
Em geral, a integração pode ser reduzida à replicação de dados:
- catálogo (produtos, categorias);
- dados de estoque (saldos de produtos em armazéns e preços);
- clientes;
- pedidos;
Magento oferece uma classe separada de objetos para manipulação de dados no banco de dados -
Clientes e pedidos geralmente são replicados na outra direção – do Magento para sistemas ERP externos. Portanto, é mais simples com eles, no lado do Magento você só precisa selecionar os dados apropriados e depois “balas voaram do nosso lado".
Princípios de registro de dados em um banco de dados
No momento, a criação de objetos salvos no banco de dados programaticamente no Magento é feita através
function __construct (MagentoCmsModelBlockFactory $blockFactory) {
$this->blockFactory = $blockFactory;
}
/** @var MagentoCmsModelBlock $block */
$block = $this->blockFactory->create();
e a gravação no banco de dados é feita através
function __construct (MagentoCmsApiBlockRepositoryInterface $blockRepo) {
$this->blockRepo = $blockRepo;
}
$this->blockRepo->save($block);
A abordagem “Fábrica” e “Repositório” pode ser usada para todos os principais modelos no domínio Magento 2.
Informações básicas do produto
Estou olhando para uma estrutura de dados que corresponde à versão Magento 2.3. As informações mais básicas sobre o produto estão na tabela catalog_product_entity
(cadastro do produto):
entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at
Estou limitado a um tipo de produto (type_id='simple'
), um conjunto de atributos padrão (attribute_set_id=4
) e ignorar atributos has_options
и required_options
. Já que os atributos entity_id
, created_at
и updated_at
são gerados automaticamente, então, na verdade, para adicionar um novo produto, basta definir sku
. Eu faço isso:
/** @var MagentoCatalogApiDataProductInterfaceFactory $factProd */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
/** @var MagentoCatalogApiDataProductInterface $prod */
$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$repoProd->save($prod);
e recebo uma exceção:
The "Product Name" attribute value is empty. Set the attribute and try again.
Eu adiciono o nome do produto à solicitação e recebo uma mensagem informando que o atributo está faltando Price
. Após adicionar o preço, o produto é adicionado ao banco de dados:
$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$prod->setName($name);
$prod->setPrice($price);
$repoProd->save($prod);
O nome do produto é armazenado na tabela de atributos varchar do produto (catalog_product_entity_varchar
), preço - na tabela catalog_product_entity_decimal
. Antes de adicionar um produto, é aconselhável indicar explicitamente que estamos utilizando a vitrine administrativa para importar dados:
/** @var MagentoStoreModelStoreManagerInterface $manStore */
$manStore->setCurrentStore(0);
Atributos Adicionais
Processar atributos adicionais do produto usando Magento é um prazer. Modelo de dados EAV para entidades principais (ver tabela eav_entity_type
) é um dos principais recursos desta plataforma. Simplesmente adicionamos os atributos apropriados ao modelo do produto:
$prodEntity->setData('description', $desc);
$prodEntity->setData('short_description', $desc_short);
// или
$prodEntity->setDescription($desc);
$prodEntity->setShortDescription($desc_short);
e ao salvar o modelo através do objeto repo:
$repoProd->save($prod);
atributos adicionais também serão armazenados nas tabelas de banco de dados correspondentes.
Dados de inventário
Em termos simples - a quantidade de produto em estoque. No Magento 2.3, as estruturas do banco de dados que descrevem o formato para armazenar dados de inventário são
/** @var MagentoCatalogModelProduct $prodEntity */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
$inventory = [
'is_in_stock' => true,
'qty' => 1234
];
$prodEntity->setData('quantity_and_stock_status', $inventory);
$repoProd->save($prodEntity);
mídia
Via de regra, o suporte de mídia de um produto para um cliente em uma loja (e-commerce) difere do suporte de mídia do mesmo produto para um funcionário em um sistema de contabilidade interna (ERP). No primeiro caso é aconselhável mostrar o produto cara a cara, no segundo basta dar uma ideia geral do produto. Porém, transferir pelo menos a imagem primária de um produto é bastante comum. case
ao importar dados.
Ao adicionar uma imagem através do painel de administração, a imagem é primeiro salva em um diretório temporário (./pub/media/tmp/catalog/product
) e somente ao salvar o produto é movido para o diretório de mídia (./pub/media/catalog/product
). Além disso, quando adicionada através do painel de administração, a imagem é marcada 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 alguma razão, a mídia é vinculada somente após salvar o produto e recuperá-lo novamente do repositório. E você precisa especificar o atributo label
ao adicionar uma entrada à galeria de mídia do produto (caso contrário, receberemos uma exceção Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516
).
categoria
Freqüentemente, a estrutura de categorias da loja e do aplicativo de back-end ou a colocação de produtos neles podem diferir significativamente. As estratégias para migrar dados sobre categorias e produtos dentro delas dependem de muitos fatores. Neste exemplo, mantenho o seguinte:
- as categorias de backend e loja são comparadas por nome;
- se for importada uma categoria que não esteja na loja, ela será criada na categoria raiz (
Default Category
) e seu posterior posicionamento no catálogo da loja é assumido manualmente; - um produto é atribuído a uma categoria somente quando é criado na loja (primeira importação);
Informações básicas sobre a categoria estão na tabela catalog_category_entity
(catálogo de categorias). Criando uma categoria no Magento:
/** @var MagentoCatalogApiDataCategoryInterfaceFactory $factCat */
/** @var MagentoCatalogApiCategoryRepositoryInterface $repoCat */
$cat = $factCat->create();
$cat->setName($name);
$cat->setIsActive(true);
$repoCat->save($cat);
A vinculação de um produto a uma categoria é realizada através do ID da categoria e do SKU do produto:
/** @var MagentoCatalogModelCategoryProductLinkFactory $factCatProdLink */
/** @var MagentoCatalogApiCategoryLinkRepositoryInterface $repoCatLink */
$link = $factCatProdLink->create();
$link->setCategoryId($catMageId);
$link->setSku($prodSku);
$repoCatLink->save($link);
No total
Escrever código para adicionar um produto programaticamente ao Magento 2 é bastante fácil. Combinei tudo o que foi declarado acima em um módulo de demonstração “fl32:import:prod
, que importa os produtos descritos no arquivo JSON "
[
{
"sku": "...",
"name": "...",
"desc": "...",
"desc_short": "...",
"price": ...,
"qty": ...,
"categories": ["..."],
"image_path": "..."
}
]
As fotos para importação estão no catálogo ./etc/data/img
.
O tempo para importar 10 produtos usando esse método é de cerca de 10 segundos no meu laptop. Se desenvolvermos mais esta ideia, é fácil chegar à conclusão de que cerca de 3600 produtos podem ser importados por hora, e pode levar cerca de 100 horas para importar 30 mil produtos. Substituir um laptop por um servidor permite amenizar um pouco a situação. Talvez até várias vezes. Mas não por ordens de grandeza. Talvez esta velocidade e lentidão seja, em certa medida, uma das razões para o surgimento do projeto
Uma solução radical para aumentar a velocidade de importação poderia ser a entrada direta no banco de dados, mas neste caso todas as “guloseimas” relativas à extensibilidade do Magento são perdidas - você terá que fazer tudo “avançado” sozinho. No entanto, vale a pena. Se der certo, considerarei a abordagem com gravação direta no banco de dados no próximo artigo.
Fonte: habr.com