Magento 2: importáljon termékeket közvetlenül az adatbázisba
В előző cikk Leírtam a termékek Magento 2-be történő importálásának folyamatát a szokásos módon - modelleken és tárolókon keresztül. A szokásos módszer nagyon alacsony adatfeldolgozási sebességgel rendelkezik. A laptopom körülbelül egy terméket termelt másodpercenként. Ebben a folytatásban fontolóra veszem a termék importálásának alternatív módját - az adatbázisba való közvetlen belépéssel, a szabványos Magento 2 mechanizmusok (modellek, gyárak, adattárak) megkerülésével. A termékek importálásához szükséges lépések sorrendje bármely olyan programozási nyelvhez igazítható, amely képes együttműködni a MySQL-lel.
A felelősség megtagadása: A Magento kész funkcionalitással rendelkezik adatimportálás és nagy valószínűséggel elég lesz neked. Ha azonban teljesebb ellenőrzésre van szüksége az importálási folyamat felett, és nem korlátozódik a CSV-fájl elkészítésére a meglévőhöz, üdvözöljük a cat.
A két cikk megírásából származó kód megtekinthető a Magento modulban "flancer32/mage2_ext_demo_import". Íme néhány korlátozás, amelyeket követtem a demómodul kódjának egyszerűsítése érdekében:
A termékeket csak létrehozzák, nem frissítik.
Egy raktár
Csak a kategórianevek importálása történik, szerkezetük nélkül
Az adatszerkezetek megfelelnek a 2.3-as verziónak
JSON egyetlen termék importálásához:
{
"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"
}
Az import főbb szakaszainak áttekintése
magának a terméknek a regisztrációja
kapcsolat a termék és a webhely között
alapvető terméktulajdonságok (EAV)
készletadatok (a termék raktáron lévő mennyisége)
média (képek)
kapcsolat a katalóguskategóriákkal
Termék regisztráció
Az alapvető termékinformációkat a 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`)
)
A terméknyilvántartásban való bejegyzés létrehozásához szükséges minimális információk:
attribute_set_id
sku
további:
type_id — ha nem adjuk meg, akkor az „egyszerű” lesz használva
Az adatbázisba való közvetlen íráshoz magának a Magento DB adapterét használom:
Az újonnan regisztrált terméknek még nincs neve vagy leírása. Mindez keresztül történik EAV attribútumok. Az alábbiakban felsoroljuk azokat az alapvető termékattribútumokat, amelyek szükségesek ahhoz, hogy a termék helyesen jelenjen meg az előlapon:
name
price
description
short_description
status
tax_class_id
url_key
visibility
Egy ilyen termékhez külön attribútumot adunk (az attribútum kódjából az azonosító és az attribútum típusának megszerzésének részleteit kihagyjuk):
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);
}
}
Az attribútumkód segítségével meghatározzuk annak azonosítóját és adattípusát (datetime, decimal, int, text, varchar), majd írja be az adminisztrációs ablak adatait a megfelelő táblába (store_id = 0).
Miután hozzáadta a fenti attribútumokat a termékhez, ez a kép jelenik meg az adminisztrációs panelen:
Leltári adatok
A Magento 2.3-as verziójától kezdve két párhuzamos táblakészlet található, amelyek a készletinformációkat (termékmennyiség) tárolják:
cataloginventory_*: régi szerkezet;
inventory_*: új struktúra (MSI - Multi Source Inventory);
Mindkét struktúrához hozzá kell adni a készletadatokat, mert az új szerkezet még nem teljesen független a régitől (nagyon valószínű, hogy azért default raktár az új struktúrában egy asztal szerepel cataloginventory_stock_status mint inventory_stock_1).
katalóguskészlet_
A Magneto 2.3 telepítésekor kezdetben 2 bejegyzésünk van store_website, amely két webhelynek felel meg - adminisztratív és fő kliens:
Vagyis a régi struktúránkban csak egy „raktár” van (stock), és az adminisztratív webhelyhez kapcsolódik. Újak hozzáadása az adminisztrációs panelen keresztül sources/stocks az MSI-ben (új struktúra) nem eredményez új bejegyzéseket cataloginventory_stock.
A régi szerkezetű termékek készletadatait kezdetben táblázatokban rögzítjük:
cataloginventory_stock_item
cataloginventory_stock_status
katalóguskészlet_készlet_cikk
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óguskészlet_készlet_állapota
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);
}
leltár_
Kezdetben a készletadatok tárolására szolgáló új struktúra 1 "forrás"(inventory_source):
«Forrás» a termékek fizikai tárolását jelöli (a rekord fizikai koordinátákat és levelezési címet tartalmaz). "Raktár"több "forrás" logikai egyesülése (inventory_source_stock_link)
azon a szinten, amelyen az értékesítési csatornához való kapcsolódás megtörténik (inventory_stock_sales_channel)
type |code|stock_id|
-------|----|--------|
website|base| 1|
Az adatszerkezetből ítélve különféle típusú értékesítési csatornákat feltételezünk, de alapértelmezés szerint csak a kapcsolat „készlet"-""(a weboldalra mutató hivatkozás a weboldal kódját követi - base).
egy"raktár"többhez köthető"forrás"és egy "forrás"- többnek"raktárak"(sok-több kapcsolat). A kivételek alapértelmezettek"forrás"És"raktár". Nem kapcsolódnak újra más entitásokhoz (kódszintű korlátozás - a hiba "Nem menthető az alapértelmezett forráshoz vagy az alapértelmezett készlethez kapcsolódó hivatkozás"). A Magento 2 MSI-struktúrájáról további részletek a cikkben találhatók.Raktárkezelési rendszer CQRS és Event Sourcing használatával. Tervezés”.
Az alapértelmezett konfigurációt fogom használni, és minden készletinformációt hozzáadok a forráshoz default, amely részt vesz a kóddal rendelkező weboldalhoz kapcsolódó értékesítési csatornában base (az üzlet elülső részének felel meg - lásd store_website):
Miután hozzáadta a készletadatokat a termékhez az adminisztrációs panelen, ez a kép jelenik meg:
Média
Amikor „kézi” képet ad hozzá egy termékhez az adminisztrációs panelen keresztül, a vonatkozó információkat a következő táblázatok írják le:
catalog_product_entity_media_gallery: médianyilvántartás (kép- és videofájlok);
catalog_product_entity_media_gallery_value: a média összekapcsolása termékekkel és bemutatókkal (lokalizáció);
catalog_product_entity_media_gallery_value_to_entity: a média csak a termékekhez való összekapcsolása (feltehetően a termék alapértelmezett médiatartalma);
catalog_product_entity_varchar: Itt tárolódnak azok a szerepek, amelyekben a képet használják;
és maguk a képek a könyvtárba kerülnek ./pub/media/catalog/product/x/y/Ahol x и y — a képfájl nevének első és második betűje. Például fájl image.png néven kell menteni ./pub/media/catalog/product/i/m/image.png, így a platform képként használhatja a katalógusból származó termékek leírásakor.
catalog_product_entity_media_gallery
Regisztráció feladva ./pub/media/catalog/product/ médiafájl (magának a fájl elhelyezésének folyamatáról ebben a cikkben nem lesz szó):
A regisztrált médiafájlt a megfelelő termékhez társítjuk anélkül, hogy bármilyen kirakathoz kötnénk. Nem világos, hogy pontosan hol használják ezeket az adatokat, és miért nem lehet hozzáférni az előző táblázat adataihoz, de ez a tábla létezik, és az adatok akkor íródnak bele, amikor képet adnak a termékhez. Szóval ennyi.
catalog_category_product: kapcsolat a termékek és a kategóriák között;
catalog_category_entity_*: EAV attribútumértékek;
Kezdetben egy üres Magento alkalmazásban a kategória-nyilvántartás 2 kategóriát tartalmaz (az oszlopneveket lerövidítettem: crt - created_at, upd - updated_at):
Az id=1 kategória a teljes Magento katalógus gyökere, és nem érhető el sem az adminisztrációs panelen, sem a címlapon. Kategória id=2 (Alapértelmezett kategória) a fő webhely fő áruházának gyökérkategóriája (Fő webáruház) az alkalmazás telepítésekor jön létre (lásd. Admin / Üzletek / Minden üzlet). Ráadásul magának az üzletnek a gyökérkategóriája sem érhető el elöl, csak az alkategóriái.
Mivel ennek a cikknek a témája továbbra is a termékekre vonatkozó adatok importálása, ezért a kategóriák létrehozásakor nem használok közvetlen adatbevitelt az adatbázisba, hanem maga a Magento által biztosított osztályokat (modellek és repository-ok) fogom használni. Az adatbázisba való közvetlen belépés csak az importált termék kategóriához való társítására szolgál (a kategória a nevével párosul, és az egyeztetés során a kategóriaazonosító lekérésre kerül):
Miután hozzáadott egy terméklinket az „1. kategória” és a „2. kategória” kategóriákhoz, a termékadatok az adminisztrációs panelen valahogy így néznek ki:
További műveletek
Az adatok importálása után a következő további lépéseket kell végrehajtania:
adatindexelés: hívás a konzolban ./bin/magento indexer:reindex;
Termékek az adminisztrációs panelen további műveletek elvégzése után:
és elöl:
Összegzés
Ugyanaz a termékkészlet (10 darab), mint az előző cikkben, legalább egy nagyságrenddel gyorsabban importálódik (1 másodperc a 10-hez képest). A sebesség pontosabb becsléséhez nagyobb számú termékre van szükség – több százra, vagy jobb esetben több ezerre. Azonban még ilyen kis bemeneti adatok mellett is azt a következtetést vonhatjuk le, hogy a Magento által biztosított eszközök (modellek és adattárak) használata jelentős (hangsúlyozom - sok!) felgyorsítja a szükséges funkcionalitás fejlesztését, ugyanakkor jelentősen (hangsúlyozom - sok!) csökkenti az adatok adatbázisba kerülésének sebességét.
Ennek eredményeként a víz nedvesnek bizonyult, és ez nem kinyilatkoztatás. Most azonban megvan a kód, amellyel játszhatok, és talán érdekesebb következtetésekre jutok.