Magento 2 : importer des produits directement dans la base de données
В article précédent J'ai décrit le processus d'importation de produits dans Magento 2 de la manière habituelle - via des modèles et des référentiels. La méthode habituelle a une vitesse de traitement des données très faible. Mon ordinateur portable produisait environ un produit par seconde. Dans cette suite, j'envisage une manière alternative d'importer un produit - par entrée directe dans la base de données, en contournant les mécanismes standards de Magento 2 (modèles, usines, référentiels). La séquence d'étapes pour importer des produits peut être adaptée à n'importe quel langage de programmation pouvant fonctionner avec MySQL.
Clause de non-responsabilité : Magento a des fonctionnalités prêtes à l'emploi pour importation de données et, très probablement, cela vous suffira. Cependant, si vous avez besoin d'un contrôle plus complet sur le processus d'importation, sans vous limiter à la préparation d'un fichier CSV pour ce que vous avez, bienvenue sur cat.
Le code résultant de la rédaction des deux articles est consultable dans le module Magento "flancer32/mage2_ext_demo_import". Voici quelques restrictions que j'ai suivies pour simplifier le code du module de démonstration :
Les produits sont uniquement créés, pas mis à jour.
Un entrepôt
Seuls les noms de catégories sont importés, sans leur structure
Les structures de données sont conformes à la version 2.3
JSON pour importer un seul produit :
{
"sku": "MVA20D-UBV-3",
"name": "Заглушка для пломбировки ВА47-29 IEK",
"desc": "Обеспечение доступа к устройствам ...",
"desc_short": "Заглушка для пломбировки ВА47-29 IEK предназначена для ...",
"price": 5.00,
"qty": 25,
"categories": ["Категория 1", "Категория 2"],
"image_path": "mva20d_ubv_3.png"
}
Aperçu des principales étapes de l'importation
enregistrement du produit lui-même
connexion entre le produit et le site Web
attributs de base du produit (EAV)
données d'inventaire (quantité de produit en stock)
médias (images)
connexion avec les catégories du catalogue
Enregistrement du produit
Des informations de base sur le produit peuvent être trouvées dans catalog_product_entity:
CREATE TABLE `catalog_product_entity` (
`entity_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Entity Id',
`attribute_set_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Attribute Set ID',
`type_id` varchar(32) NOT NULL DEFAULT 'simple' COMMENT 'Type ID',
`sku` varchar(64) DEFAULT NULL COMMENT 'SKU',
`has_options` smallint(6) NOT NULL DEFAULT '0' COMMENT 'Has Options',
`required_options` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Required Options',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation Time',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Update Time',
PRIMARY KEY (`entity_id`),
KEY `CATALOG_PRODUCT_ENTITY_ATTRIBUTE_SET_ID` (`attribute_set_id`),
KEY `CATALOG_PRODUCT_ENTITY_SKU` (`sku`)
)
Les informations minimales requises pour créer une entrée dans le registre du produit sont :
attribute_set_id
sku
supplémentaire:
type_id — si nous ne le précisons pas, alors 'simple' sera utilisé
Pour écrire directement dans la base de données, j'utilise l'adaptateur DB de Magento lui-même :
Après avoir enregistré le produit auprès de catalog_product_entity il devient visible dans le panneau d'administration, dans la grille des produits (Catalogue/Produits).
Relation entre le produit et le site Web
L'association du produit au site détermine dans quels magasins et vitrines le produit sera disponible en vitrine.
Le produit nouvellement enregistré n'a pas encore de nom ni de description. Tout cela se fait à travers Attributs EAV. Voici une liste des attributs de base du produit qui sont nécessaires pour que le produit s'affiche correctement sur le devant :
name
price
description
short_description
status
tax_class_id
url_key
visibility
Un attribut distinct est ajouté à un produit comme celui-ci (les détails d'obtention de l'identifiant et du type de l'attribut à partir de son code sont omis) :
public function create($prodId, $attrCode, $attrValue)
{
$attrId = /* get attribute ID by attribute code */
$attrType = /* get attribute type [datetime|decimal|int|text|varchar]) by attribute code */
if ($attrId) {
/** @var MagentoFrameworkAppResourceConnection $this->resource */
/** @var MagentoFrameworkDBAdapterPdoMysql $conn */
$conn = $this->resource->getConnection();
$tblName = 'catalog_product_entity_' . $attrType;
$table = $this->resource->getTableName($tblName);
$bind = [
'attribute_id' => $attrId,
'entity_id' => $prodId,
/* put all attributes to default store view with id=0 (admin) */
'store_id' => 0,
'value' => $attrValue
];
$conn->insert($table, $bind);
}
}
À l'aide du code d'attribut, nous déterminons son identifiant et son type de données (datetime, decimal, int, text, varchar), puis écrivez les données de la fenêtre d'administration dans la table appropriée (store_id = 0).
Après avoir ajouté les attributs ci-dessus au produit, vous obtenez cette image dans le panneau d'administration :
Données d'inventaire
À partir de la version 2.3 dans Magento, il existe deux ensembles parallèles de tables qui permettent de stocker les informations d'inventaire (quantité de produit) :
cataloginventory_*: structure ancienne ;
inventory_*: nouvelle structure (MSI - Multi Source Inventory) ;
Vous devez ajouter des données d'inventaire aux deux structures, car la nouvelle structure n'est pas encore complètement indépendante de l'ancienne (il est très probable que pour default entrepôt dans la nouvelle structure, une table est impliquée cataloginventory_stock_status comme inventory_stock_1).
catalogueinventaire_
Lors du déploiement de Magneto 2.3, nous avons initialement 2 entrées dans store_website, ce qui correspond à deux sites - administratif et client principal :
Autrement dit, dans notre ancienne structure, il n'y a qu'un seul « entrepôt » (stock) et il est lié au site administratif. En ajouter de nouveaux via le panneau d'administration sources/stocks dans MSI (nouvelle structure) n'entraîne pas de nouvelles entrées dans cataloginventory_stock.
Les données d'inventaire sur les produits de l'ancienne structure sont initialement enregistrées dans des tableaux :
cataloginventory_stock_item
cataloginventory_stock_status
catalogueinventory_stock_item
function createOldItem($prodId, $qty)
{
$isQtyDecimal = (((int)$qty) != $qty);
$isInStock = ($qty > 0);
/** @var MagentoFrameworkAppResourceConnection $this->resource */
/** @var MagentoFrameworkDBAdapterPdoMysql $conn */
$conn = $this->resource->getConnection();
$table = $this->resource->getTableName('cataloginventory_stock_item');
$bind = [
'product_id' => $prodId,
/* we use one only stock in 'cataloginventory' structure by default */
'stock_id' => 1,
'qty' => $qty,
'is_qty_decimal' => $isQtyDecimal,
'is_in_stock' => $isInStock,
/* default stock is bound to admin website (see `cataloginventory_stock`) */
'website_id' => 0
];
$conn->insert($table, $bind);
}
catalogueinventory_stock_status
function createOldStatus($prodId, $qty)
{
$isInStock = ($qty > 0);
/** @var MagentoFrameworkAppResourceConnection $this->resource */
/** @var MagentoFrameworkDBAdapterPdoMysql $conn */
$conn = $this->resource->getConnection();
$table = $this->resource->getTableName('cataloginventory_stock_status');
$bind = [
'product_id' => $prodId,
/* we use one only stock in 'cataloginventory' structure by default */
'stock_id' => 1,
'qty' => $qty,
'stock_status' => MagentoCatalogInventoryApiDataStockStatusInterface::STATUS_IN_STOCK,
/* default stock is bound to admin website (see `cataloginventory_stock`) */
'website_id' => 0
];
$conn->insert($table, $bind);
}
inventaire_
Initialement, la nouvelle structure de stockage des données d'inventaire contient 1 "source"(inventory_source):
«Source» représente le stockage physique des produits (l'enregistrement contient les coordonnées physiques et l'adresse postale). "Entrepôt" est une union logique de plusieurs " sources " (inventory_source_stock_link)
au niveau où s'effectue la connexion au canal de vente (inventory_stock_sales_channel)
type |code|stock_id|
-------|----|--------|
website|base| 1|
À en juger par la structure des données, différents types de canaux de vente sont supposés, mais par défaut uniquement la connexion "stock"-"site de NDN Collective"(le lien vers le site suit le code du site - base).
Un "entrepôt"peut être lié à plusieurs"les sources"et une "source" - à plusieurs "entrepôts"(relation plusieurs-à-plusieurs). Les exceptions sont par défaut "source"Et"entrepôt". Ils ne sont pas ré-liés à d'autres entités (limitation au niveau du code - l'erreur "Impossible d'enregistrer le lien lié à la source par défaut ou au stock par défaut"). Plus de détails sur la structure MSI dans Magento 2 peuvent être trouvés dans l'article «Système de gestion d'entrepôt utilisant CQRS et Event Sourcing. Conception«.
J'utiliserai la configuration par défaut et ajouterai toutes les informations d'inventaire à la source default, qui intervient dans le canal de vente associé au site Internet avec le code base (correspond à la devanture du magasin - voir store_website):
Après avoir ajouté les données d'inventaire au produit dans le panneau d'administration, vous obtenez cette image :
médias
Lors de l'ajout « manuel » d'une image à un produit via le panneau d'administration, les informations pertinentes sont consignées dans les tableaux suivants :
catalog_product_entity_media_gallery: registre des médias (images et fichiers vidéo) ;
catalog_product_entity_media_gallery_value: relier les médias aux produits et aux vitrines (localisation) ;
catalog_product_entity_media_gallery_value_to_entity: relier les médias aux produits uniquement (vraisemblablement du contenu multimédia par défaut pour le produit) ;
catalog_product_entity_varchar: Les rôles dans lesquels l'image est utilisée sont stockés ici ;
et les images elles-mêmes sont enregistrées dans le répertoire ./pub/media/catalog/product/x/y/Où x и y — les première et deuxième lettres du nom du fichier image. Par exemple, fichier image.png doit être enregistré sous ./pub/media/catalog/product/i/m/image.png, afin que la plateforme puisse l'utiliser comme image lors de la description des produits du catalogue.
catalog_product_entity_media_gallery
S'inscrire publié dans ./pub/media/catalog/product/ fichier multimédia (le processus de placement du fichier lui-même n'est pas abordé dans cet article) :
Nous associons le fichier multimédia enregistré au produit correspondant sans être lié à une quelconque vitrine. On ne sait pas exactement où ces données sont utilisées et pourquoi il est impossible d'accéder aux données du tableau précédent, mais ce tableau existe et les données y sont écrites lorsqu'une image est ajoutée au produit. Alors c'est tout.
Un fichier média peut être utilisé avec différents rôles (le code d'attribut correspondant est indiqué entre parenthèses) :
Base(image)
Petite image (small_image)
La vignette (thumbnail)
Image d'échantillon (swatch_image)
Lier des rôles à un fichier multimédia est exactement ce qui se passe dans catalog_product_entity_varchar. Le code de liaison est similaire au code du "Attributs de base du produit«.
Après avoir ajouté une image au produit dans le panneau d'administration, elle ressemble à ceci :
catégorie
Principaux tableaux contenant des données par catégorie :
catalog_category_entity: registre des catégories;
catalog_category_product: connexion entre produits et catégories ;
Initialement, dans une application Magento vide, le registre des catégories contient 2 catégories (j'ai raccourci les noms des colonnes : crt - created_at, upd - updated_at):
La catégorie avec id=1 est la racine de l'ensemble du catalogue Magento et n'est disponible ni dans le panneau d'administration ni sur la page d'accueil. Catégorie avec id=2 (Catégorie par défaut) est la catégorie racine du magasin principal du site principal (Boutique du site Web principal) créé lors du déploiement de l'application (voir. Admin / Magasins / Tous les magasins). De plus, la catégorie racine du magasin lui-même n’est pas non plus disponible à l’avant, uniquement ses sous-catégories.
Le sujet de cet article étant toujours l'importation de données sur les produits, je n'utiliserai pas la saisie directe dans la base de données lors de la création de catégories, mais j'utiliserai les classes fournies par Magento lui-même (modèles et référentiels). La saisie directe dans la base de données permet uniquement d'associer le produit importé à une catégorie (la catégorie est mise en correspondance par son nom, et l'identifiant de la catégorie est récupéré lors de la mise en correspondance) :
Après avoir ajouté un lien de produit vers les catégories « Catégorie 1 » et « Catégorie 2 », les détails du produit dans le panneau d'administration ressemblent à ceci :
Actions supplémentaires
Une fois l'importation des données terminée, vous devez effectuer les étapes supplémentaires suivantes :
indexation des données : appel dans la console ./bin/magento indexer:reindex;
Produits dans le panneau d'administration après avoir effectué des actions supplémentaires :
et à l'avant :
Résumé
Le même ensemble de produits (10 pièces) que dans l'article précédent est importé au moins un ordre de grandeur plus rapidement (1 seconde contre 10). Pour estimer plus précisément la vitesse, vous avez besoin d'un plus grand nombre de produits - plusieurs centaines, voire des milliers. Cependant, même avec une si petite taille de données d'entrée, on peut conclure que l'utilisation des outils fournis par Magento (modèles et référentiels) est significative (j'insiste - significativement!) accélérer le développement des fonctionnalités requises, mais en même temps de manière significative (j'insiste - significativement!) Réduisez la vitesse à laquelle les données entrent dans la base de données.
Du coup, l'eau s'est avérée humide et ce n'est pas une révélation. Cependant, j'ai maintenant le code avec lequel jouer et peut-être arriver à des conclusions plus intéressantes.