Uues Ma olen kirjeldanud toodete importimise protsessi Magento 2 tavapĂ€rasel viisil â mudelite ja hoidlate kaudu. TavapĂ€rane meetod erineb vĂ€ga madala andmete töötlemise kiirusest. Minu sĂŒlearvutis tuli umbes ĂŒks toode sekundis. KĂ€esolevas jĂ€tkuks kĂ€sitlen alternatiivset toodete importimise meetodit â otse andmebaasi kirjutamist, sĂŒdames Magento 2 tavalisi mehhanisme (mudelid, tehased, hoidlad). NĂ€idatud sammude jĂ€rjekord, mis tagab toodete impordi, saab olla kohandatud igaks programmeerimiskeeleks, mis suudab töötada MySQL-iga.
MÀrkus: Magento sisaldab valmis funktsionaalsust ja tÔenÀoliselt on see piisav. Kuid kui vajate impordiprotsessi jaoks tÀiendavat kontrolli, mis ei piirdu ainult CSV-faili ettevalmistamisega, olete teretulnud allolevale.

Kood, mis saadakse pĂ€rast nende kahe artikli kirjutamist, on saadaval Magento moodulis ââ. Siin on mĂ”ned piirangud, millest olen pidanud kinni, et lihtsustada demo mooduli koodi:
- Tooteid luuakse ainult, mitte uuendatakse.
- Ăks ladu
- Imporditakse ainult kategooriate nimetusi, ilma nende struktuurita.
- Andmestruktuurid vastavad versioonile 2.3.
JSON ĂŒhe toote impordiks:
{
"sku": "MVA20D-UBV-3",
"name": "Tihend VA47-29 IEK",
"desc": "Juhtmete seadmete ...",
"desc_short": "Tihend VA47-29 IEK on mÔeldud ...",
"price": 5.00,
"qty": 25,
"categories": ["Kategooria 1", "Kategooria 2"],
"image_path": "mva20d_ubv_3.png"
}Impressioonide peamised etapid
- toote registreerimine
- toote ja veebisaidi vaheline seos
- toote pÔhijooned (EAV)
- inventariteave (toote kogus laos)
- meedia (pildid)
- ĂŒhendus katalooge kategooriatega
Produkti registreerimine
Toote pÔhiteave asub 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`)
)Minimaalselt vajalik teave toote registrisse salvestamiseks:
atribuut_set_idsku
lisavÀÀrne:
type_idâ kui me ei mÀÀra, siis kasutatakse 'simple'
Otsese andmebaasi kirjutamiseks kasutan Magento enda DB-adapterit:
function create($sku, $typeId, $attrSetId)
{
\/** @var MagentoFrameworkAppResourceConnection $this->resource *\/
\/** @var MagentoFrameworkDBAdapterPdoMysql $conn *\/
$conn = $this->resource->getConnection();
$table = $this->resource->getTableName('catalog_product_entity');
$bind = [
'sku' => $sku,
'type_id' => $typeId,
'attribute_set_id' => $attrSetId
];
$conn->insert($table, $bind);
$result = $conn->lastInsertId($table);
return $result;
}PÀrast toote registreerimist catalog_product_entity muutub see nÀhtavaks administraatori paneelil, toote gridi (Kataloog / Toote).

Toote ja veebisaidi seos
Toote seos veebisaidiga mÀÀrab, millistes poodides ja millistel vitriinidel toode esitleb front-endis.
function linkToWebsite($prodId, $websiteId)
{
\/** @var MagentoFrameworkAppResourceConnection $this->resource *\/
\/** @var MagentoFrameworkDBAdapterPdoMysql $conn *\/
$conn = $this->resource->getConnection();
$table = $this->resource->getTableName('catalog_product_website');
$bind = [
'product_id' => $prodId,
'website_id' => $websiteId
];
$conn->insert($table, $bind);
}
Toote pÔhivÀÀrused
NĂŒĂŒd registreeritud tootel ei ole veel nime ega kirjeldust. KĂ”ik see toimub lĂ€bi . Siin on loetelu toote pĂ”hivÀÀrustest, mis on vajalikud, et toodet piisavalt Ă”igesti front-endis kuvada:
nimipricekirjelduslĂŒhikirjeldusstaatusmaksu_klass_idurl_klahvnĂ€havus
Eriline vÀÀrus tootele lisatakse nii (ĂŒksikasjad identifikaatori ja tĂŒĂŒbi hankimise kohta koodi jĂ€rgi on jĂ€etud vĂ€lja):
public function create($prodId, $attrCode, $attrValue)
{
$attrId = \/** hankige vÀÀruse ID vastavalt koodile *\/
$attrType = \/** hankige vÀÀruse tĂŒĂŒp [datetime|decimal|int|text|varchar] koodi jĂ€rgi *\/
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,
\/** asetage kÔik vÀÀrtused vaikimisi poe vaate jaoks, mille id=0 (admin) *\/
'store_id' => 0,
'value' => $attrValue
];
$conn->insert($table, $bind);
}
}Koodi jĂ€rgi mÀÀrame selle ID ja andmetĂŒĂŒbi (datetime, decimal, int, ntext, varchar), seejĂ€rel kirjutame vastavatele tabelitesse andmed haldusvaate jaoks (store_id = 0).
Pafter nende vÀÀruste lisamist tootele saadakse administraatori paneelil selline pilt:

Inventariandmed
Alates versioonist 2.3 eksisteerib Magento jaoks samaaegselt kaks tabelite kogumit, mis tagavad laoseisu teabe sÀilitamise (toote kogus):
cataloginventory_*: vana struktuur;inventory_*: uus struktuur (MSI â Multi Source Inventory);
Inventariseerimisandmeid tuleb lisada mÔlemasse struktuuri, kuna uus struktuur ei ole veel tÀielikult vanast sÔltumatu (vÀga sarnane on, et SeejÀrel kÀivitame exec kÀsu ja ootame 5000 sekundit, et jÀtkata jÀlgimist: uue struktuuri laos kasutatakse tabelit cataloginventory_stock_status vaikimisi inventory_stock_1).
cataloginventory_
Magento 2.3 kĂ€ivitamisel on meil algselt 2 kirjet store_website, mis vastab kahele veebisaidile â haldus- ja pĂ”hiklientide leht:
website_id|code |name |sort_order|default_group_id|is_default|
----------|-----|------------|----------|----------------|----------|
0|admin|Admin | 0| 0| 0|
1|base |Peamine veebisait| 0| 1| 1|Tabelis cataloginventory_stock on meil ainult ĂŒks kirje:
stock_id|website_id|stock_name|
--------|----------|----------|
1| 0|Vaikimisi |See tĂ€hendab, et meil on vanas struktuuris ainult ĂŒks «lager» (stock) ja see on seotud haldusveebisaidiga. Uute lisamine admin paneeli ei too kaasa uusi kirjeid allikad/stocks Uute toodete inventarimisel MSI-s (uus struktuur) ei teki uusi kirjeid cataloginventory_stock.
Toodete inventariteave vanas struktuuris on algselt kirjutatud tabelitesse:
cataloginventory_stock_itemcataloginventory_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,
\/* me kasutame vaikimisi ĂŒhte lattu 'cataloginventory' struktuuris *\/
'stock_id' => 1,
'qty' => $qty,
'is_qty_decimal' => $isQtyDecimal,
'is_in_stock' => $isInStock,
\/* vaikimisi ladustamine on seotud haldusveebisaidiga (vaata `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,
\/* me kasutame vaikimisi ĂŒhte lattu 'cataloginventory' struktuuris *\/
'stock_id' => 1,
'qty' => $qty,
'stock_status' => MagentoCatalogInventoryApiDataStockStatusInterface::STATUS_IN_STOCK,
\/* vaikimisi ladustamine on seotud haldusveebisaidiga (vaata `cataloginventory_stock`) *\/
'website_id' => 0
];
$conn->insert($table, $bind);
}inventory_
Algusest peale sisaldab uus struktuur inventarite andmete salvestamiseks 1 «allikas» (inventory_source):
source_code|name |enabled|description |latitude|longitude|country_id|...|
-----------|--------------|-------|--------------|--------|---------|----------|...|
default |Vaikimisi allikas| 1|Vaikimisi allikas|0.000000| 0.000000|US |...|ja ĂŒks «lager» (inventory_stock):
stock_id|name |
--------|-------------|
1|Vaikimisi lager|«Allikas» on fĂŒĂŒsiline ladustamine toodetele (salvestus sisaldab fĂŒĂŒsilisi koordinaate ja postiaadressi). «Ladu» on loogiline ĂŒhendus mitmete «allikate» (inventory_source_stock_link)
link_id|stock_id|source_code|priority|
-------|--------|-----------|--------|
1| 1|default | 1|tasandil, kus toimub mĂŒĂŒgikanali seondamine (inventory_stock_sales_channel)
type |code|stock_id|
-------|----|--------|
website|base| 1|Andmestruktuuri pĂ”hjal eeldatakse erinevaid mĂŒĂŒgikanaleid, kuid vaikimisi kasutatakse vaid seost «stock«-«veebisait» (link veebisaidile toimub veebisaidi koodi kaudu â base).
Ăks «lager» vĂ”ib olla seotud mitme «allika«, ja ĂŒks «allikas» â mitme «lao» (suhted «palju-palju»). Erandiks on default «allikas" ja "lager«. Neid ei seostata teiste olenditega (kooditasandi piirang â ilmneb tĂ”rge «Can not save link related to Default Source or Default Stock«). TĂ€iendava teabe jaoks MSI struktuuri kohta Magento 2-s vĂ”id lugeda artiklit ««.
Kasutan default-konfiguratsiooni ja lisan kogu inventari teabe allikasse SeejĂ€rel kĂ€ivitame exec kĂ€su ja ootame 5000 sekundit, et jĂ€tkata jĂ€lgimist:, mis on seotud mĂŒĂŒgikanaliga, mis on seotud veebisaidi koodiga base (seondub poe kliendi osaga â vt. store_website):
function createNewItem($sku, $qty)
{
/** @var MagentoFrameworkAppResourceConnection $this->resource *///*
/** @var MagentoFrameworkDBAdapterPdoMysql $conn *//*
$conn = $this->resource->getConnection();
$table = $this->resource->getTableName('inventory_source_item');
$bind = [
'source_code' => 'default',
'sku' => $sku,
'quantity' => $qty,
'status' => MagentoInventoryApiApiDataSourceItemInterface::STATUS_IN_STOCK
];
$conn->insert($table, $bind);
}PÀrast inventariteabe lisamist tootele adminpaneelis nÀeb see vÀlja nagu:

Meedia
KÀsitsi tootele piltide lisamisel adminpaneelist salvestatakse vastav teave jÀrgmistes tabelites:
catalog_product_entity_media_gallery: meediaregister (pildid ja videofailid);catalog_product_entity_media_gallery_value: meedia sidumine toodetega ja vitriinidega (lokaliseerimine);catalog_product_entity_media_gallery_value_to_entity: meedia sidumine ainult toodetega (eeldatavasti default meedia sisu toote jaoks);catalog_product_entity_varchar: siin salvestatakse rollid, milles pilti kasutatakse;
ja ise pildid salvestatakse katalooge .\/pub\/media\/catalog\/product\/x\/y\/, kus x ja y â failinime esimene ja teine tĂ€ht. NĂ€iteks, fail image.png peaks olema salvestatud kui ./pub/media/catalog/product/i/m/image.png, et platform saaks selle kasutada toote katalogi kirjeldamiseks pildina.
catalog_product_entity_media_gallery
Registreerime asukoha .\/pub\/media\/catalog\/product\/ meediafail (faili paigutamise protsessi selles artiklis ei kÀsitleta):
function createMediaGallery($imgPathPrefixed)
{
$attrId = 0 get attribute ID by attribute code 'media_gallery' *\/
0 @var MagentoFrameworkAppResourceConnection $this->resource *\/
0 @var MagentoFrameworkDBAdapterPdoMysql $conn *\/
$conn = $this->resource->getConnection();
$table = $this->resource->getTableName('catalog_product_entity_media_gallery');
$bind = [
'attribute_id' => $attrId,
'value' => $imgPathPrefixed,
0 'image' or 'video' *\/
'media_type' => 'image',
'disabled' => false
];
$conn->insert($table, $bind);
$result = $conn->lastInsertId($table);
return $result;
}Uuele meediafailile antakse identifikaator.
catalog_product_entity_media_gallery_value
Sidume registreeritud meediafaili vastava tootega default-poes:
function createGalleryValue($mediaId, $prodId)
{
0 @var MagentoFrameworkAppResourceConnection $this->resource *\/
0 @var MagentoFrameworkDBAdapterPdoMysql $conn *\/
$conn = $this->resource->getConnection();
$table = $this->resource->getTableName('catalog_product_entity_media_gallery_value');
$bind = [
'value_id' => $mediaId,
0 use admin store view by default *\/
'store_id' => 0,
'entity_id' => $prodId,
'label' => null,
0 we have one only image *\/
'position' => 1,
'disabled' => false
];
$conn->insert($table, $bind);
}catalog_product_entity_media_gallery_value_to_entity
Sidume registreeritud meediafaili vastava tootega ilma seotuse mÀÀramata. Pole selge, kus neid andmeid tegelikult kasutatakse ja miks ei saa pöörduda eelneva tabeli andmete poole, kuid see tabel eksisteerib ja andmeid kirjutatakse sinna, kui pilt tootele lisatakse. Nii see on.
function createGalleryValueToEntity($mediaId, $prodId)
{
0 @var MagentoFrameworkAppResourceConnection $this->resource *\/
0 @var MagentoFrameworkDBAdapterPdoMysql $conn *\/
$conn = $this->resource->getConnection();
$table = $this->resource->getTableName('catalog_product_entity_media_gallery_value_to_entity');
$bind = [
'value_id' => $mediaId,
'entity_id' => $prodId
];
$conn->insert($table, $bind);
}catalog_product_entity_varchar
Meediafailide kasutamiseks on erinevad rollid (vastava attribuudi kood on sulgudes):
- Base (
image) - Small Image (
small_image) - Thumbnail (
thumbnail) - Swatch Image (
swatch_image)
Rollide seondumine meediafailiga toimub just siin catalog_product_entity_varchar. Seondumise kood on analoogne koodile jaotises "Toote pÔhivÀÀrused«.
PÀrast toote pildi lisamist adminpaneelis nÀeb see vÀlja nii:

Kategooriad
Peamised tabelid, kus hoitakse andmeid kategooriate kohta:
catalog_category_entity: kategooriate registri;catalog_category_product: toodete ja kategooriate seos;catalog_category_entity_*: EAV-attribuutide vÀÀrtused;
Alguses, tĂŒhjas Magento rakenduses sisaldab kategooriate registris 2 kategooriat (ma lĂŒhendasin veergude nimetusi: crt â created_at, upd â updated_at):
entity_id|attribute_set_id|parent_id|crt|upd|path|position|level|children_count|
---------|----------------|---------|---|---|----|--------|-----|--------------|
1| 3| 0|...|...|1 | 0| 0| 1|
2| 3| 1|...|...|1/2 | 1| 1| 0|Kategooria id=1 on kogu Magento katalooge juur ja seda ei ole vÔimalik nÀha ei administraatoris ega esiplaanil. Kategooria id=2 (Default Category) on juurkategooria pÔhipoe jaoks pÔhilehe (PÔhisaidi pood), mis luuakse rakenduse juurutamisel (vt. Admin / Kauplused / KÔik kauplused). Pealegi ei ole poe juurkategooria esiplaanil samuti kergesti kÀtetÔmbamine, vaid ainult selle alamkategooriad.
Kuna selle artikli teemaks on toodete andmete import, mitte otse andmebaasi kirjutamine kategooriate loomisel, kasutame Magento enda pakutavaid klasse (mudelid ja repodid). Otse andmebaasi kirjutamist kasutatakse ainult imporditud toote seose loomiseks kategooriaga (kategooria mÀÀramine toimub selle nime jÀrgi, mÀÀramise kÀigus saadakse kategooria id):
function create($prodId, $catId)
{
/** @var MagentoFrameworkAppResourceConnection $this->resource *///
/** @var MagentoFrameworkDBAdapterPdoMysql $conn *///
$conn = $this->resource->getConnection();
$table = $this->resource->getTableName('catalog_category_product');
$bind = [
'category_id' => $catId,
'product_id' => $prodId,
];
$conn->insert($table, $bind);
}PÀrast toote seose loomist kategooriatega "Kategooria 1" ja "Kategooria 2" nÀevad toote detailid administraatoris vÀlja umbes nii:

TĂ€iendavad toimingud
PÀrast andmete importimise lÔpetamist tuleb teha jÀrgmised tÀiendavad toimingud:
- andmete indekseerimine: kÀsu kÀivitamine terminalis
./bin/magento indexer:reindex; - toodete/kategooriate URL-ide taaskoostamine: saab kasutada laiendust "«
Tooted administraatoris pÀrast tÀiendavate toimingute tegemist:

ja esiplaanil:

Elulookirjeldus
Sama tootesett (10 tĂŒkki), mis oli eelnevas artiklis, imporditakse vĂ€hemalt ĂŒhe jĂ€rgu vĂ”rra kiiremini (1 sekund vĂ”rreldes 10 sekundi). TĂ€pse kiirusmÔÔtmiseks on vaja suuremat toote arvu â mitu sada, veel parem tuhat. Siiski, isegi sellise vĂ€ikese sisendandmete suuruse juures vĂ”ib jĂ€reldada, et Magento poolest pakutavate tööriistade (mudelid ja repod) kasutamine on mĂ€rgatavalt (toonitan â oluliselt!) kiirendab vajaliku funktsionaalsuse arendamist, kuid samas (toon selgelt vĂ€lja â oluliselt!) vĂ€hendab andmete jĂ”udmise kiirust andmebaasi.
LĂ”ppkokkuvĂ”ttes osutus vesi mĂ€rjaks ja see ei ole mingi ĂŒllatus. Sellegipoolest on mul nĂŒĂŒd kood, millega mĂ€ngida ja vĂ”ib-olla teha huvitavamaid jĂ€reldusi.
Allikas: habr.com
