Magento 2: importation de produits à partir de sources externes

Magento est une solution de commerce électronique, c'est-à-dire plus axé sur la vente de produits que sur les ventes d'accompagnement d'entrepôt, de logistique ou de comptabilité financière. D'autres applications (comme les systèmes ERP) conviennent mieux aux compagnons. Par conséquent, assez souvent dans la pratique de l'utilisation de Magento, la tâche d'intégrer un magasin avec ces autres systèmes (par exemple, avec 1C) se pose.


Dans l'ensemble, l'intégration peut être réduite à la réplication des données par:


  • catalogue (produits, catégories);
  • données d'inventaire (stocks de produits dans les entrepôts et prix);
  • aux clients;
  • les commandes;

Magento pour la manipulation des données dans la base de données propose une classe d'objets distincte - les référentiels . En raison des spécificités de Magento, l'ajout de données à la base de données via des référentiels est facile à coder, mais cela se produit, disons, pas rapidement. Dans cette publication, je considère les principales étapes de l'ajout par programme d'un produit à Magento 2 d'une manière "classique" - en utilisant des classes de repo.


Les clients et les commandes sont généralement répliqués de l'autre côté - de Magento aux systèmes ERP externes. Par conséquent, c'est plus simple avec eux, du côté de Magento, il vous suffit de sélectionner les données appropriées, puis " les balles tirées de notre côté ".


Principes d'écriture des données dans la base de données


À l'heure actuelle, la création d'objets stockés dans la base de données par programmation dans Magento se fait via Factory :


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

et écrire dans la base de données via le référentiel :


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

L'approche Factory et Repository peut être utilisée pour tous les principaux modèles du domaine Magento 2.


Informations de base sur le produit


J'envisage une structure de données correspondant à Magento 2.3. Les informations produit les plus élémentaires se catalog_product_entity dans la table catalog_product_entity (registre de produits):


 entity_id attribute_set_id type_id sku has_options required_options created_at updated_at 

Je type_id='simple' limite type_id='simple' un type de produit ( type_id='simple' ), un ensemble d' attribute_set_id=4 par défaut ( attribute_set_id=4 ) et has_options required_options attributs has_options et required_options . Étant donné que les attributs entity_id , created_at et updated_at sont générés automatiquement, il nous suffit donc de spécifier sku pour ajouter un nouveau produit. Je fais ça:


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

et obtenez une exception:


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

J'ajoute le nom du produit à la demande et je reçois un message indiquant que l'attribut Price est manquant. Après avoir ajouté le prix, le produit tombe dans la base de données:


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

Le nom du produit est stocké dans la table des attributs varchar du produit ( catalog_product_entity_varchar ), le prix est stocké dans la table catalog_product_entity_decimal . Avant d'ajouter un produit, il est conseillé d'indiquer explicitement que nous utilisons une vitrine administrative pour importer des données:


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

Attributs supplémentaires


Le traitement des attributs de produit supplémentaires avec Magento est un plaisir. Le modèle de données EAV pour les entités principales (voir le tableau eav_entity_type ) est l'une des principales caractéristiques de cette plate-forme. Ajoutez simplement les attributs appropriés au modèle de produit:


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

et lors de l'enregistrement du modèle via l'objet repo:


 $repoProd->save($prod); 

des attributs supplémentaires seront également stockés dans les tables de base de données correspondantes.


Données d'inventaire


D'une manière simple - la quantité de produit en stock. Dans Magento 2.3, les structures de base de données décrivant le format de stockage des données d'inventaire sont considérablement différentes de ce qu'elles étaient auparavant. Cependant, l'ajout de quantités de produits en stock via un modèle de produit n'est pas beaucoup plus difficile que l'ajout d'autres attributs:


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

Médias


En règle générale, le support média pour un produit pour un client dans un magasin (commerce électronique) est différent du support média pour le même produit pour un employé dans un système de comptabilité interne (ERP). Dans le premier cas, il est souhaitable de montrer le "visage du produit", dans le second - il suffit de donner une idée générale du produit. Néanmoins, le transfert d'au moins l'image principale du produit est un case assez courant lors de l'importation de données.


Lors de l'ajout d'une image via le panneau d'administration, l'image est d'abord enregistrée dans le répertoire temporaire ( ./pub/media/tmp/catalog/product ) et uniquement lorsque le produit est enregistré est déplacé vers le répertoire multimédia ( ./pub/media/catalog/product ). De plus, lors de l'ajout via le small_image administration, l'image est définie sur les small_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); 

Pour une raison quelconque, le support n'est lié qu'après avoir préalablement enregistré le produit et l'avoir reçu à nouveau du référentiel. Et vous devez spécifier l'attribut label lors de l'ajout d'une entrée à la galerie multimédia du produit (sinon, nous obtenons l'exception d' Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516 défini Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516 ).


Les catégories


Souvent, la structure des catégories de magasins et des applications dorsales ou le placement de produits dans celles-ci peut varier considérablement. Les stratégies de transfert de données sur les catégories et les produits qu'elles contiennent dépendent de nombreux facteurs. Dans cet exemple, je m'en tiens aux points suivants:


  • les catégories de backend et de store sont comparées par nom;
  • si une catégorie est importée qui ne se trouve pas dans le magasin, elle est créée sous la catégorie racine (catégorie Default Category ) et son positionnement ultérieur dans le catalogue du magasin est supposé manuellement;
  • un produit n'est affecté à une catégorie que lorsqu'il est créé dans un magasin (première importation);

Les informations de base sur les catégories se catalog_category_entity dans la table catalog_category_entity (catalogue de catégories). Créer une catégorie dans 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); 

Le produit est affecté à une catégorie par ID de catégorie et SKU de produit:


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


Écrire du code pour ajouter un produit à Magento 2 par programmation est très facile. Tout ce qui précède, je l'ai réduit au module de démonstration " flancer32 / mage2_ext_demo_import ". Il n'y a qu'une seule commande console fl32:import:prod dans le fl32:import:prod , qui importe les produits décrits dans le fichier JSON " ./etc/data/products.json ":


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

Les images à importer se trouvent dans le répertoire ./etc/data/img .


Le temps d'importation de 10 produits de cette manière est d'environ 10 secondes sur mon ordinateur portable. Si nous développons davantage cette idée, il est facile de conclure qu'environ 3 600 produits peuvent être importés par heure, et environ 30 heures peuvent être prises pour importer des produits 100K. Le remplacement d'un ordinateur portable par un serveur vous permet de quelque peu atténuer la situation. Peut-être même parfois. Mais pas par ordre de grandeur. Peut-être vitesse la lenteur est dans une certaine mesure l'une des raisons de l'émergence du projet magento / async-import .


Une décision cardinale d'augmenter la vitesse d'importation peut être d'écrire directement dans la base de données, mais dans ce cas, tous les "petits pains" concernant l'extensibilité de Magento sont perdus - vous devez tout faire vous-même "avancé". Cependant, cela en vaut la peine. Si cela fonctionne, je considérerai l'approche avec enregistrement direct dans la base de données dans le prochain article.

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


All Articles