ProHoster > Blog > uprava > Magento 2: uvoz proizvoda izravno u bazu podataka
Magento 2: uvoz proizvoda izravno u bazu podataka
В prethodni članak Opisao sam proces uvoza proizvoda u Magento 2 na uobičajen način – kroz modele i repozitorije. Uobičajena metoda ima vrlo nisku brzinu obrade podataka. Moje prijenosno računalo proizvodilo je otprilike jedan proizvod u sekundi. U ovom nastavku razmatram alternativni način uvoza proizvoda - izravnim unosom u bazu podataka, zaobilazeći standardne Magento 2 mehanizme (modeli, tvornice, repozitoriji). Redoslijed koraka za uvoz proizvoda može se prilagoditi bilo kojem programskom jeziku koji može raditi s MySQL-om.
Izjava o odricanju od odgovornosti: Magento ima gotovu funkcionalnost za uvoz podataka i, najvjerojatnije, bit će vam dovoljno. Međutim, ako trebate potpuniju kontrolu nad postupkom uvoza, ne ograničavajući se na pripremu CSV datoteke za ono što imate, dobrodošli u cat.
Kod koji je nastao pisanjem oba članka može se vidjeti u Magento modulu "flancer32/mage2_ext_demo_import". Evo nekih ograničenja kojih sam se pridržavao kako bih pojednostavio kod demo modula:
Proizvodi se samo kreiraju, a ne ažuriraju.
Jedno skladište
Uvoze se samo nazivi kategorija, bez njihove strukture
Strukture podataka u skladu su s verzijom 2.3
JSON za uvoz jednog proizvoda:
{
"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"
}
Pregled glavnih faza uvoza
registracija samog proizvoda
veza između proizvoda i web stranice
osnovne karakteristike proizvoda (EAV)
podaci o zalihama (količina proizvoda na skladištu)
mediji (slike)
povezanost s kataloškim kategorijama
Registracija proizvoda
Osnovne informacije o proizvodu možete pronaći u 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`)
)
Minimalni podaci potrebni za stvaranje unosa u registar proizvoda su:
attribute_set_id
sku
dodatno:
type_id — ako to ne navedemo, koristit će se 'jednostavno'
Za izravno pisanje u bazu podataka koristim DB adapter samog Magenta:
Novoregistrirani proizvod još nema naziv ni opis. Sve se to radi putem EAV atributi. Ovdje je popis osnovnih atributa proizvoda koji su potrebni da bi proizvod bio ispravno prikazan na prednjoj strani:
name
price
description
short_description
status
tax_class_id
url_key
visibility
Ovakvom proizvodu dodaje se zaseban atribut (pojedinosti o dobivanju identifikatora i vrsti atributa iz njegovog koda su izostavljeni):
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);
}
}
Pomoću šifre atributa određujemo njegov ID i tip podataka (datetime, decimal, int, text, varchar), zatim upiši podatke za administrativni prozor u odgovarajuću tablicu (store_id = 0).
Nakon dodavanja gornjih atributa proizvodu, dobit ćete ovu sliku u administratorskoj ploči:
Podaci o zalihama
Počevši od verzije 2.3 u Magentu, postoje dva paralelna skupa tablica koje omogućuju pohranu informacija o inventaru (količina proizvoda):
cataloginventory_*: stara struktura;
inventory_*: nova struktura (MSI - Multi Source Inventory);
Trebate dodati podatke o inventaru u obje strukture, jer nova struktura još nije potpuno neovisna o staroj (vrlo je vjerojatno da će za default skladište u novoj strukturi uključen je stol cataloginventory_stock_status kao inventory_stock_1).
kataloški inventar_
Prilikom postavljanja Magneta 2.3 u početku imamo 2 unosa store_website, što odgovara dvije stranice - administrativnoj i glavnoj klijentskoj:
Odnosno, u našoj staroj strukturi postoji samo jedno "skladište" (stock) i povezan je s administrativnom web stranicom. Dodavanje novih putem administratorske ploče sources/stocks u MSI (nova struktura) ne rezultira novim unosima u cataloginventory_stock.
Podaci o zalihama o proizvodima u staroj strukturi početno se bilježe u tablicama:
cataloginventory_stock_item
cataloginventory_stock_status
kataloški inventar_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);
}
kataloški_inventar_stanje_zaliha
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);
}
inventar_
U početku nova struktura za pohranu podataka o zalihama sadrži 1 "izvor'(inventory_source):
«Источник» predstavlja fizičko skladište za proizvode (zapis sadrži fizičke koordinate i poštansku adresu). "Skladište"logičan je spoj nekoliko "izvora" (inventory_source_stock_link)
na razini na kojoj se javlja veza s kanalom prodaje (inventory_stock_sales_channel)
type |code|stock_id|
-------|----|--------|
website|base| 1|
Sudeći prema strukturi podataka, pretpostavljaju se različite vrste prodajnih kanala, ali prema zadanim postavkama samo veza “zaliha"-"web stranicu"(veza do web stranice slijedi kod web stranice - base).
Jedan "dućan"može se povezati s nekoliko"izvori"i jedan "izvor" - na nekoliko "skladišta"(odnos više-prema-više). Iznimke su zadane "izvor"A"dućan". Nisu ponovno povezani s drugim entitetima (ograničenje na razini koda - pogreška "Nije moguće spremiti vezu koja se odnosi na zadani izvor ili zadanu zalihu"). Više detalja o MSI strukturi u Magento 2 možete pronaći u članku “Sustav upravljanja skladištem koristeći CQRS i Event Sourcing. Oblikovati”.
Koristit ću zadanu konfiguraciju i dodati sve informacije o inventaru u izvor default, koji je uključen u prodajni kanal povezan s web mjestom s kodom base (odgovara prednjem dijelu trgovine - vidi store_website):
Nakon dodavanja podataka o inventaru proizvodu na administrativnoj ploči, dobit ćete ovu sliku:
media
Prilikom “ručnog” dodavanja slike proizvodu kroz administrativnu ploču, relevantni podaci su zapisani u sljedećim tablicama:
catalog_product_entity_media_gallery: registar medija (slike i video datoteke);
catalog_product_entity_media_gallery_value: povezivanje medija s proizvodima i izlozima (lokalizacija);
catalog_product_entity_media_gallery_value_to_entity: povezivanje medija samo s proizvodima (vjerojatno zadani medijski sadržaj za proizvod);
catalog_product_entity_varchar: Ovdje su pohranjene uloge u kojima se slika koristi;
a same slike spremaju se u imenik ./pub/media/catalog/product/x/y/Gdje x и y — prvo i drugo slovo naziva slikovne datoteke. Na primjer, datoteka image.png treba spremiti kao ./pub/media/catalog/product/i/m/image.png, kako bi ga platforma mogla koristiti kao sliku pri opisu proizvoda iz kataloga.
katalog_proizvod_entitet_medijska_galerija
Registar objavljen u ./pub/media/catalog/product/ medijska datoteka (sam proces postavljanja datoteke nije razmatran u ovom članku):
Registriranu medijsku datoteku povezujemo s odgovarajućim proizvodom bez vezivanja za bilo koji izlog. Nije jasno gdje se točno koriste ti podaci i zašto je nemoguće pristupiti podacima iz prethodne tablice, ali ova tablica postoji i podaci se u nju upisuju kada se doda slika na proizvod. Znaci to je to.
Medijska datoteka može se koristiti s različitim ulogama (odgovarajući kod atributa naveden je u zagradama):
Baza(image)
Mala slika (small_image)
Sličica (thumbnail)
Uzorak slike (swatch_image)
Povezivanje uloga s medijskom datotekom točno je ono što se događa u catalog_product_entity_varchar. Kod za vezanje sličan je kodu u "Osnovne karakteristike proizvoda”.
Nakon dodavanja slike proizvodu u administratorskoj ploči izgleda ovako:
Категории
Glavne tablice koje sadrže podatke po kategorijama:
catalog_category_entity: registar kategorija;
catalog_category_product: povezanost proizvoda i kategorija;
catalog_category_entity_*: vrijednosti atributa EAV;
U početku, u praznoj Magento aplikaciji, registar kategorija sadrži 2 kategorije (skratio sam nazive stupaca: crt - created_at, upd - updated_at):
Kategorija s id=1 korijen je cijelog Magento kataloga i nije dostupna niti u admin panelu niti na naslovnoj stranici. Kategorija s id=2 (Zadana kategorija) je korijenska kategorija za glavnu trgovinu glavne stranice (Glavna trgovina web stranice) stvoreno kada je aplikacija postavljena (pogledajte. Admin / Trgovine / Sve trgovine). Štoviše, korijenska kategorija same trgovine također nije dostupna na prednjoj strani, samo njezine potkategorije.
Budući da je tema ovog članka još uvijek uvoz podataka o proizvodima, neću koristiti direktan unos u bazu prilikom kreiranja kategorija, već ću koristiti klase koje nudi sam Magento (modeli i repozitoriji). Izravan unos u bazu podataka koristi se samo za povezivanje uvezenog proizvoda s kategorijom (kategorija se uparuje prema nazivu, a ID kategorije se dohvaća tijekom uparivanja):
Nakon dodavanja veze proizvoda u kategorije "Kategorija 1" i "Kategorija 2", pojedinosti o proizvodu na administratorskoj ploči izgledaju otprilike ovako:
Dodatne radnje
Nakon dovršetka uvoza podataka morate izvršiti sljedeće dodatne korake:
indeksiranje podataka: poziv u konzoli ./bin/magento indexer:reindex;
Proizvodi u administratorskoj ploči nakon izvođenja dodatnih radnji:
a sprijeda:
Rezime
Isti skup proizvoda (10 komada) kao u prethodnom članku uvozi se barem jedan red veličine brže (1 sekunda u odnosu na 10). Za točniju procjenu brzine potreban vam je veći broj proizvoda - nekoliko stotina, ili još bolje tisuća. No, čak i s tako malom količinom ulaznih podataka, možemo zaključiti da je korištenje alata koje Magento nudi (modeli i repozitoriji) značajno (naglašavam - mnogo!) ubrzati razvoj potrebne funkcionalnosti, ali u isto vrijeme značajno (naglašavam - mnogo!) smanjiti brzinu kojom podaci ulaze u bazu podataka.
Kao rezultat toga, voda se pokazala mokrom i to nije otkriće. Međutim, sada imam kôd s kojim se mogu igrati i možda doći do nekih zanimljivijih zaključaka.