Magento 2: importu produktojn rekte en la datumbazon
В antaŭa artikolo Mi priskribis la procezon de importado de produktoj en Magento 2 laŭ la kutima maniero - per modeloj kaj deponejoj. La kutima metodo havas tre malaltan datumtraktadrapidecon. Mia tekkomputilo produktis proksimume unu produkton je sekundo. En ĉi tiu daŭrigo, mi konsideras alternativan manieron importi produkton - per rekta eniro en la datumbazon, preterirante la normajn mekanismojn Magento 2 (modeloj, fabrikoj, deponejoj). La sekvenco de paŝoj por importi produktojn povas esti adaptita al iu ajn programlingvo kiu povas funkcii kun MySQL.
malgarantio: Magento havas pretajn funkciojn por importado de datumoj kaj, plej verŝajne, ĝi sufiĉos por vi. Tamen, se vi bezonas pli kompletan kontrolon pri la importprocezo, ne limigita al preparado de CSV-dosiero por tio, kion vi havas, bonvenon al kato.
La kodo rezultanta de skribado de ambaŭ artikoloj videblas en la Magento-modulo "flancer32/mage2_ext_demo_import". Jen kelkaj limigoj, kiujn mi sekvis por simpligi la demomodulkodon:
Produktoj estas nur kreitaj, ne ĝisdatigitaj.
Unu magazeno
Nur kategorinomoj estas importitaj, sen ilia strukturo
Datumaj strukturoj konformas al versio 2.3
JSON por importi ununuran produkton:
{
"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"
}
Superrigardo de la ĉefaj etapoj de importado
registrado de la produkto mem
konekto inter produkto kaj retejo
Bazaj produktaj atributoj (EAV)
inventardatumoj (kvanto de produkto en stoko)
amaskomunikilaro (bildoj)
rilato kun katalogaj kategorioj
Produkta Registrado
Bazaj produktaj informoj troveblas en 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`)
)
La minimuma informo necesa por krei eniron en la produkta registro estas:
attribute_set_id
sku
pliaj:
type_id — se ni ne specifas ĝin, tiam 'simple' estos uzata
Por skribi rekte al la datumbazo, mi uzas la DB-adaptilon de Magento mem:
La lastatempe registrita produkto ankoraŭ ne havas nomon aŭ priskribon. Ĉio ĉi estas farita tra EAV-atributoj. Jen listo de bazaj produktaj atributoj, kiuj necesas por ke la produkto estu ĝuste montrita ĉe la fronto:
name
price
description
short_description
status
tax_class_id
url_key
visibility
Aparta atributo estas aldonita al produkto kiel ĉi tiu (la detaloj pri akiro de la identigilo kaj speco de la atributo de ĝia kodo estas preterlasitaj):
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);
}
}
Uzante la atributan kodon, ni determinas ĝian id kaj datumtipo (datetime, decimal, int, text, varchar), tiam skribu la datumojn por la administra fenestro en la taŭgan tabelon (store_id = 0).
Post aldoni la suprajn atributojn al la produkto, vi ricevas ĉi tiun bildon en la administra panelo:
Invenraj datumoj
Komencante de versio 2.3 en Magento, ekzistas du paralelaj aroj de tabeloj, kiuj provizas stokajn informojn pri stokregistro (produkta kvanto):
cataloginventory_*: malnova strukturo;
inventory_*: nova strukturo (MSI - Multi Source Inventory);
Vi devas aldoni inventarajn datumojn al ambaŭ strukturoj, ĉar la nova strukturo ankoraŭ ne estas tute sendependa de la malnova (tre verŝajne ke por default magazeno en la nova strukturo tablo estas implikita cataloginventory_stock_status kiel inventory_stock_1).
katalogoinventario_
Dum deplojado de Magneto 2.3 ni komence havas 2 enirojn store_website, kiu respondas al du retejoj - administra kaj ĉefa kliento:
Tio estas, en nia malnova strukturo estas nur unu "stokejo" (stock) kaj ĝi estas ligita al la administra retejo. Aldonante novajn tra la administra panelo sources/stocks en MSI (nova strukturo) ne rezultigas novajn enskribojn cataloginventory_stock.
Stokregistraj datumoj pri produktoj en la malnova strukturo estas komence registritaj en tabeloj:
cataloginventory_stock_item
cataloginventory_stock_status
cataloginventory_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);
}
cataloginventory_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);
}
inventaro_
Komence, la nova strukturo por stoki inventardatumojn enhavas 1 "fonto"(inventory_source):
«Fonto» reprezentas la fizikan stokadon por produktoj (la registro enhavas fizikajn koordinatojn kaj poŝtadreson). "Stokejo"estas logika kuniĝo de pluraj "fontoj" (inventory_source_stock_link)
je la nivelo ĉe kiu okazas la ligo al la venda kanalo (inventory_stock_sales_channel)
type |code|stock_id|
-------|----|--------|
website|base| 1|
Juĝante laŭ la datumstrukturo, diversaj specoj de vendaj kanaloj estas supozitaj, sed defaŭlte nur la konekto "provizo"-"retejo"(la ligilo al la retejo sekvas la retejo-kodon - base).
Unu"magazeno"povas esti ligita al pluraj"al fontoj"kaj unu"fonto"- al pluraj"magazenoj"(multaj-al-multaj rilato). La esceptoj estas defaŭltaj "fonto"Kaj"magazeno". Ili ne estas religitaj al aliaj estaĵoj (limigo ĉe la kodnivelo - la eraro "Ne povas konservi ligon rilatan al Defaŭlta Fonto aŭ Defaŭlta Stoko"). Pli da detaloj pri la MSI-strukturo en Magento 2 troveblas en la artikolo "Mastruma sistemo de magazeno uzante CQRS kaj Event Sourcing. Dezajno".
Mi uzos la defaŭltan agordon kaj aldonos ĉiujn inventarajn informojn al la fonto default, kiu estas implikita en la venda kanalo asociita kun la retejo kun la kodo base (korespondas al la antaŭa fino de la vendejo - vidu store_website):
Post aldoni stokajn datumojn al la produkto en la administra panelo, vi ricevas ĉi tiun bildon:
Amaskomunikilaro
Kiam "mane" aldonas bildon al produkto per la administra panelo, la koncernaj informoj estas notitaj en la sekvaj tabeloj:
catalog_product_entity_media_gallery: amaskomunikila registro (bildoj kaj videodosieroj);
catalog_product_entity_media_gallery_value: ligi amaskomunikilaron al produktoj kaj montrofenestroj (lokigo);
catalog_product_entity_media_gallery_value_to_entity: ligi amaskomunikilaron al produktoj nur (supozeble defaŭlta amaskomunikila enhavo por la produkto);
catalog_product_entity_varchar: La roloj en kiuj la bildo estas uzata estas konservitaj ĉi tie;
kaj la bildoj mem estas konservitaj al la dosierujo ./pub/media/catalog/product/x/y/kie x и y — la unua kaj dua literoj de la bildodosiernomo. Ekzemple, dosiero image.png devus esti konservita kiel ./pub/media/catalog/product/i/m/image.png, por ke la platformo povu uzi ĝin kiel bildon priskribante produktojn de la katalogo.
catalog_product_entity_media_galerio
Registriĝi afiŝita ./pub/media/catalog/product/ amaskomunikila dosiero (la procezo de metado de la dosiero mem ne estas diskutita en ĉi tiu artikolo):
Ni asocias la registritan amaskomunikilan dosieron kun la responda produkto sen esti ligitaj al iu ajn vendejo. Ne estas klare, kie ĝuste ĉi tiuj datumoj estas uzataj kaj kial estas neeble aliri la datumojn de la antaŭa tabelo, sed ĉi tiu tabelo ekzistas kaj la datumoj estas skribitaj al ĝi kiam bildo estas aldonita al la produkto. Do jen.
Multimedia dosiero povas esti uzata kun malsamaj roloj (la responda atributkodo estas indikita inter krampoj):
Bazo(image)
Malgranda Bildo (small_image)
Bildeto (thumbnail)
Swatch Bildo (swatch_image)
Ligi rolojn al amaskomunikila dosiero estas ĝuste tio, kio okazas catalog_product_entity_varchar. La deviga kodo estas simila al la kodo en la "Bazaj produktaj atributoj".
Post aldoni bildon al la produkto en la administra panelo, ĝi aspektas jene:
Kategorioj
Ĉefaj tabeloj enhavantaj datumojn laŭ kategorio:
catalog_category_entity: registro de kategorioj;
catalog_category_product: rilato inter produktoj kaj kategorioj;
catalog_category_entity_*: EAV-atributaj valoroj;
Komence, en malplena Magento-aplikaĵo, la kategorio-registro enhavas 2 kategoriojn (mi mallongigis la kolonnomojn: crt - created_at, upd - updated_at):
La kategorio kun id=1 estas la radiko de la tuta Magento-katalogo kaj ne haveblas nek en la administra panelo nek sur la frontpaĝo. Kategorio kun id=2 (Defaŭlta Kategorio) estas la radika kategorio por la ĉefa butiko de la ĉefa retejo (Ĉefa Reteja Vendejo) kreita dum deplojado de la aplikaĵo (vidu. Administranto / Vendejoj / Ĉiuj Vendejoj). Krome, la radika kategorio de la vendejo mem ankaŭ ne haveblas ĉe la fronto, nur ĝiaj subkategorioj.
Ĉar la temo de ĉi tiu artikolo ankoraŭ importas datumojn pri produktoj, mi ne uzos rektan eniron en la datumbazon dum kreado de kategorioj, sed uzos la klasojn provizitajn de Magento mem (modeloj kaj deponejoj). Rekta eniro en la datumbazon estas uzata nur por asocii la importitan produkton kun kategorio (la kategorio kongruas per sia nomo, kaj la kategoriidentigilo estas prenita dum kongruo):
Produktoj en la administra panelo post plenumi pliajn agojn:
kaj ĉe la fronto:
Resumo
La sama aro da produktoj (10 pecoj) kiel en la antaŭa artikolo estas importita almenaŭ grandordo pli rapide (1 sekundo kontraŭ 10). Por pli precize taksi la rapidecon, vi bezonas pli grandan nombron da produktoj - kelkcent, aŭ pli bone ankoraŭ milojn. Tamen, eĉ kun tiom malgranda grandeco de eniga datumoj, ni povas konkludi, ke la uzo de la iloj provizitaj de Magento (modeloj kaj deponejoj) estas grava (mi emfazas - multe!) akceli la disvolviĝon de la bezonata funkcieco, sed samtempe signife (mi emfazas - multe!) reduktu la rapidecon je kiu datumoj eniras la datumbazon.
Kiel rezulto, la akvo montriĝis malseka kaj ĉi tio ne estas revelacio. Tamen nun mi havas la kodon por ludi kaj eble elveni al iuj pli interesaj konkludoj.