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 - . Devido às especificidades do Magento, adicionar dados ao banco de dados através de repositórios é fácil de codificar, mas é, digamos, lento. Nesta publicação, considero os principais estágios da adição programática de um produto ao Magento 2 da maneira “clássica” - usando classes repo.
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_atEstou 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 do que aconteceu antes. Porém, adicionar a quantidade de um produto em estoque através do modelo do produto não é muito mais difícil do que adicionar outros atributos:
/** @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 “". Existe apenas um comando de console no módulo 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
