В predchádzajúci článok Proces importu produktov do Magento 2 som opísal bežným spôsobom – cez modely a úložiská. Bežná metóda má veľmi nízku rýchlosť spracovania údajov. Môj laptop produkoval asi jeden produkt za sekundu. V tomto pokračovaní uvažujem o alternatívnom spôsobe importu produktu – priamym vstupom do databázy, obídením štandardných mechanizmov Magento 2 (modely, továrne, úložiská). Postupnosť krokov na import produktov je možné prispôsobiť akémukoľvek programovaciemu jazyku, ktorý dokáže pracovať s MySQL.
Vylúčenie zodpovednosti: Magento má hotové funkcie pre import údajov a s najväčšou pravdepodobnosťou vám to bude stačiť. Ak však potrebujete úplnejšiu kontrolu nad procesom importu, ktorý sa neobmedzuje len na prípravu súboru CSV pre to, čo máte, vitajte na stránke cat.
Kód vyplývajúci z písania oboch článkov si môžete pozrieť v module Magento "flancer32/mage2_ext_demo_import". Tu sú niektoré obmedzenia, ktoré som dodržiaval, aby som zjednodušil kód demo modulu:
Produkty sú len vytvorené, nie aktualizované.
Jeden sklad
Importujú sa iba názvy kategórií bez ich štruktúry
Dátové štruktúry zodpovedajú verzii 2.3
JSON na import jedného produktu:
{
"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"
}
Prehľad hlavných fáz importu
registrácia samotného produktu
prepojenie medzi produktom a webovou stránkou
základné atribúty produktu (EAV)
skladové údaje (množstvo produktu na sklade)
médiá (obrázky)
prepojenie s katalógovými kategóriami
Registrácia produktu
Základné informácie o produkte nájdete v 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`)
)
Minimálne informácie potrebné na vytvorenie záznamu v registri produktov sú:
attribute_set_id
sku
dodatočné:
type_id — ak to nešpecifikujeme, použije sa slovo „jednoduché“.
Na priamy zápis do databázy používam DB adaptér samotného Magenta:
Novo zaregistrovaný produkt ešte nemá názov ani popis. Toto všetko sa robí cez EAV atribúty. Tu je zoznam základných atribútov produktu, ktoré sú potrebné na to, aby sa produkt správne zobrazoval na prednej strane:
name
price
description
short_description
status
tax_class_id
url_key
visibility
K takémuto produktu sa pridá samostatný atribút (podrobnosti o získaní identifikátora a typu atribútu z jeho kódu sú vynechané):
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);
}
}
Pomocou kódu atribútu určíme jeho ID a typ údajov (datetime, decimal, int, text, varchar), potom zapíšte údaje pre administratívne okno do príslušnej tabuľky (store_id = 0).
Po pridaní vyššie uvedených atribútov k produktu získate tento obrázok v administračnom paneli:
Údaje o zásobách
Od verzie 2.3 v Magento existujú dve paralelné sady tabuliek, ktoré poskytujú ukladanie informácií o zásobách (množstvo produktu):
cataloginventory_*: stará štruktúra;
inventory_*: nová štruktúra (MSI - Multi Source Inventory);
K obom štruktúram musíte pridať údaje o zásobách, pretože nová štruktúra ešte nie je úplne nezávislá od starej (je veľmi pravdepodobné, že pre default sklad v novej štruktúre je zahrnutý stôl cataloginventory_stock_status ako inventory_stock_1).
katalógový inventár_
Pri nasadzovaní Magneto 2.3 máme na začiatku 2 položky store_website, čo zodpovedá dvom stránkam - administratívnemu a hlavnému klientovi:
To znamená, že v našej starej štruktúre je len jeden „sklad“ (stock) a je prepojený s administratívnou webovou stránkou. Pridávanie nových cez administračný panel sources/stocks v MSI (nová štruktúra) nevedie k novým záznamom v cataloginventory_stock.
Údaje o zásobách o výrobkoch v starej štruktúre sa spočiatku zaznamenávajú v tabuľkách:
cataloginventory_stock_item
cataloginventory_stock_status
katalógový_zásob_položky
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);
}
katalógový_stav_skladov
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);
}
inventár_
Na začiatku nová štruktúra na ukladanie údajov o zásobách obsahuje 1 "zdroj"(inventory_source):
«Zdroj» predstavuje fyzické úložisko pre produkty (záznam obsahuje fyzické súradnice a poštovú adresu). "Sklad"je logickým spojením niekoľkých "zdrojov" (inventory_source_stock_link)
na úrovni, na ktorej dochádza k spojeniu s predajným kanálom (inventory_stock_sales_channel)
type |code|stock_id|
-------|----|--------|
website|base| 1|
Podľa štruktúry údajov sa predpokladajú rôzne typy predajných kanálov, ale štandardne iba spojenie „sklad„-“webové stránky"(odkaz na webovú stránku nasleduje za kódom webovej stránky - base).
jeden"sklad"možno prepojiť s viacerými"na zdroje"a jeden "zdroj"- viacerým"sklady"(vzťah veľa k mnohým). Výnimky sú predvolené "zdroj"A"sklad". Nie sú opätovne prepojené s inými entitami (obmedzenie na úrovni kódu – chyba “Nie je možné uložiť odkaz súvisiaci s predvoleným zdrojom alebo predvoleným skladom"). Viac podrobností o štruktúre MSI v Magento 2 nájdete v článku “Systém riadenia skladu využívajúci CQRS a Event Sourcing. Dizajn".
Použijem predvolenú konfiguráciu a do zdroja pridám všetky informácie o inventári default, ktorý je zapojený do predajného kanála spojeného s webovou stránkou s kódom base (zodpovedá prednej časti predajne - viď store_website):
Po pridaní údajov o sklade k produktu na paneli správcu získate tento obrázok:
Médiá
Pri „ručnom“ pridávaní obrázka k produktu cez administračný panel sa príslušné informácie zapíšu do nasledujúcich tabuliek:
catalog_product_entity_media_gallery: register médií (obrázky a video súbory);
catalog_product_entity_media_gallery_value: prepojenie médií s produktmi a vitrínami (lokalizácia);
catalog_product_entity_media_gallery_value_to_entity: prepojenie médií iba s produktmi (pravdepodobne predvolený mediálny obsah pre produkt);
catalog_product_entity_varchar: Tu sú uložené roly, v ktorých sa obrázok používa;
a samotné obrázky sa uložia do adresára ./pub/media/catalog/product/x/y/Kde x и y — prvé a druhé písmeno názvu súboru obrázka. Napríklad súbor image.png by mal byť uložený ako ./pub/media/catalog/product/i/m/image.png, aby ho platforma mohla použiť ako obrázok pri popise produktov z katalógu.
Catalog_product_entity_media_gallery
Registrácia zverejnená v ./pub/media/catalog/product/ mediálny súbor (proces umiestňovania samotného súboru nie je v tomto článku diskutovaný):
Registrovaný mediálny súbor spájame s príslušným produktom bez toho, aby bol viazaný na akýkoľvek výklad. Nie je jasné, kde presne sa tieto údaje používajú a prečo nie je možné získať prístup k údajom z predchádzajúcej tabuľky, ale táto tabuľka existuje a údaje sa do nej zapíšu, keď sa k produktu pridá obrázok. Takže to je všetko.
Mediálny súbor možno použiť s rôznymi rolami (zodpovedajúci kód atribútu je uvedený v zátvorkách):
základňa(image)
Malý obrázok (small_image)
miniatúra (thumbnail)
Obrázok vzorky (swatch_image)
Prepojenie rolí s mediálnym súborom je presne to, čo sa deje v catalog_product_entity_varchar. Kód väzby je podobný kódu v "Základné vlastnosti produktu".
Po pridaní obrázka k produktu na paneli administrátora to vyzerá takto:
Категории
Hlavné tabuľky obsahujúce údaje podľa kategórie:
catalog_category_entity: register kategórií;
catalog_category_product: prepojenie medzi produktmi a kategóriami;
catalog_category_entity_*: hodnoty atribútov EAV;
Spočiatku v prázdnej aplikácii Magento obsahuje register kategórií 2 kategórie (skrátil som názvy stĺpcov: crt - created_at, upd - updated_at):
Kategória s id=1 je koreňom celého katalógu Magento a nie je dostupná ani v admin paneli, ani na titulnej stránke. Kategória s id=2 (predvolené kategórie) je koreňová kategória pre hlavný obchod hlavnej stránky (Hlavná stránka obchodu) vytvorený pri nasadení aplikácie (pozri. Správca / Obchody / Všetky obchody). Navyše, koreňová kategória samotného obchodu tiež nie je k dispozícii na prednej strane, iba jej podkategórie.
Keďže témou tohto článku je stále import údajov o produktoch, nebudem pri vytváraní kategórií využívať priamy vstup do databázy, ale využijem triedy, ktoré poskytuje samotné Magento (modely a úložiská). Priamy vstup do databázy sa používa iba na priradenie importovaného produktu ku kategórii (kategória sa zhoduje s jej názvom a počas priraďovania sa získava ID kategórie):
Produkty na paneli správcu po vykonaní ďalších akcií:
a vpredu:
Zhrnutie
Rovnaká sada produktov (10 kusov) ako v predchádzajúcom článku sa dováža minimálne o rádovo rýchlejšie (1 sekunda oproti 10). Na presnejšie odhadnutie rýchlosti potrebujete väčší počet produktov – niekoľko stoviek, alebo ešte lepšie tisícky. Aj pri tak malej veľkosti vstupných údajov však môžeme konštatovať, že využitie nástrojov poskytovaných Magentom (modely a úložiská) je významné (zdôrazňujem - veľa!) urýchliť vývoj požadovanej funkcionality, no zároveň výrazne (zdôrazňujem - veľa!) znížiť rýchlosť, akou sa údaje dostávajú do databázy.
V dôsledku toho sa voda ukázala ako mokrá a to nie je zjavenie. Teraz však mám kód, s ktorým sa môžem pohrať a možno dospieť k zaujímavejším záverom.