Magento 2: importige tooted otse andmebaasi

В Eelmine artikkel Kirjeldasin toodete Magento 2-sse importimise protsessi tavapärasel viisil - mudelite ja hoidlate kaudu. Tavalisel meetodil on väga madal andmetöötluskiirus. Minu sülearvuti tootis umbes ühe toote sekundis. Selles jätkus kaalun alternatiivset viisi toote importimiseks - otse andmebaasi sisenemise teel, mööda standardsetest Magento 2 mehhanismidest (mudelid, tehased, hoidlad). Toodete importimise toimingute jada saab kohandada mis tahes programmeerimiskeelega, mis töötab MySQL-iga.

Kaebused: Magentol on valmis funktsionaalsus andmete importimine ja suure tõenäosusega sellest teile piisab. Kui aga vajate täielikumat kontrolli importimise protsessi üle, mitte ainult CSV-faili ettevalmistamisega, siis tere tulemast cat.

Magento 2: importige tooted otse andmebaasi

Mõlema artikli kirjutamisel saadud koodi saab vaadata Magento moodulis "flancer32/mage2_ext_demo_import". Siin on mõned piirangud, mida järgisin demomooduli koodi lihtsustamiseks:

  • Tooted on ainult loodud, mitte uuendatud.
  • Üks ladu
  • Imporditakse ainult kategooriate nimesid, ilma nende struktuurita
  • Andmestruktuurid vastavad versioonile 2.3

JSON ühe toote importimiseks:

{
  "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"
}

Ülevaade impordi peamistest etappidest

  • toote enda registreerimine
  • toote ja veebisaidi vaheline seos
  • toote põhiatribuudid (EAV)
  • laoandmed (toote kogus laos)
  • meedia (pildid)
  • seos kataloogikategooriatega

Toote registreerimine

Toote põhiteabe leiate aadressilt 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`)
)

Tooteregistris kande loomiseks nõutav miinimumteave on:

  • attribute_set_id
  • sku

lisaks:

  • type_id — kui me seda ei täpsusta, kasutatakse sõna "lihtne".

Otse 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 see muutub nähtavaks administraatori paneelil toote ruudustikus (Kataloog/Tooted).

Magento 2: importige tooted otse andmebaasi

Toote ja veebisaidi vaheline seos

Toote seotus saidiga määrab, millistes kauplustes ja väljapanekutes toode esiküljel saadaval on.

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);
}

Magento 2: importige tooted otse andmebaasi

Toote põhiomadused

Äsja registreeritud tootel ei ole veel nime ega kirjeldust. Kõik see tehakse läbi EAV atribuudid. Siin on nimekiri toote põhiatribuutidest, mida on vaja toote esiküljel korrektseks kuvamiseks:

  • name
  • price
  • description
  • short_description
  • status
  • tax_class_id
  • url_key
  • visibility

Sellisele tootele lisatakse eraldi atribuut (koodist identifikaatori ja atribuudi tüübi hankimise üksikasjad on välja jäetud):

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);
    }
}

Atribuudikoodi abil määrame selle ID ja andmetüübi (datetime, decimal, int, text, varchar), seejärel kirjutage haldusakna andmed vastavasse tabelisse (store_id = 0).

Pärast ülaltoodud atribuutide tootele lisamist näete administraatori paneelil järgmist pilti:

Magento 2: importige tooted otse andmebaasi

Varude andmed

Alates Magento versioonist 2.3 on kaks paralleelset tabelikomplekti, mis pakuvad laoandmete (tootekoguse) salvestamist:

  • cataloginventory_*: vana struktuur;
  • inventory_*: uus struktuur (MSI - Multi Source Inventory);

Mõlemasse struktuuri peate lisama laoandmed, kuna uus struktuur ei ole veel täiesti sõltumatu vanast (väga tõenäoline, et default ladu uues struktuuris on kaasatud laud cataloginventory_stock_status kui inventory_stock_1).

kataloogivaru_

Magneto 2.3 juurutamisel on meil esialgu 2 kirjet store_website, mis vastab kahele saidile – haldus- ja põhikliendile:

website_id|code |name        |sort_order|default_group_id|is_default|
----------|-----|------------|----------|----------------|----------|
         0|admin|Admin       |         0|               0|         0|
         1|base |Main Website|         0|               1|         1|

Tabel cataloginventory_stock meil on ainult üks sissekanne:

stock_id|website_id|stock_name|
--------|----------|----------|
       1|         0|Default   |

See tähendab, et meie vanas struktuuris on ainult üks "ladu" (stock) ja see on lingitud administratiivse veebisaidiga. Uute lisamine administraatori paneeli kaudu sources/stocks MSI-s (uus struktuur) ei too kaasa uusi kirjeid cataloginventory_stock.

Vana struktuuriga toodete laoandmed registreeritakse algselt tabelites:

  • cataloginventory_stock_item
  • cataloginventory_stock_status

katalooginventory_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);
}

kataloogivarude_varude_olek

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_

Esialgu sisaldab uus laoandmete salvestamise struktuur 1 "allikas(inventory_source):

source_code|name          |enabled|description   |latitude|longitude|country_id|...|
-----------|--------------|-------|--------------|--------|---------|----------|...|
default    |Default Source|      1|Default Source|0.000000| 0.000000|US        |...|

ja üks "ladu(inventory_stock):

stock_id|name         |
--------|-------------|
       1|Default Stock|

«Allikas» tähistab toodete füüsilist hoiukohta (kirje sisaldab füüsilisi koordinaate ja postiaadressi). "Ladu"on mitme "allika" loogiline liit (inventory_source_stock_link)

link_id|stock_id|source_code|priority|
-------|--------|-----------|--------|
      1|       1|default    |       1|

tasemel, mil toimub ühendus müügikanaliga (inventory_stock_sales_channel)

type   |code|stock_id|
-------|----|--------|
website|base|       1|

Andmestruktuuri järgi otsustades eeldatakse erinevat tüüpi müügikanaleid, kuid vaikimisi on ainult ühendus "varu"-"veebisait"(link veebisaidile järgib veebisaidi koodi - base).

üks"ladu"saab siduda mitmega"allikatest"ja üks "allikas"- mitmele"laod"(paljude-mitmele suhe). Erandid on vaikimisi "allikas"Ja"ladu". Neid ei lingita uuesti teiste üksustega (piirang koodi tasemel - viga "Vaikeallika või vaikevaruga seotud linki ei saa salvestada"). Lisateavet Magento 2 MSI struktuuri kohta leiate artiklist "Laohaldussüsteem CQRS-i ja Event Sourcingi abil. Disain"

Kasutan vaikekonfiguratsiooni ja lisan kogu laoinfo allikasse default, mis on seotud koodiga veebisaidiga seotud müügikanaliga base (vastab poe esiosale - 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 tootele laoandmete lisamist administraatoripaneelil saate järgmise pildi:

Magento 2: importige tooted otse andmebaasi

Meedia

Tootele pildi "käsitsi" lisamisel administraatori paneeli kaudu on vastav teave kirja pandud järgmistesse tabelitesse:

  • catalog_product_entity_media_gallery: meediaregister (pildid ja videofailid);
  • catalog_product_entity_media_gallery_value: meedia sidumine toodete ja vitriinidega (lokaliseerimine);
  • catalog_product_entity_media_gallery_value_to_entity: meediumi linkimine ainult toodetega (eeldatavasti toote vaikemeediumisisu);
  • catalog_product_entity_varchar: siia salvestatakse rollid, milles pilti kasutatakse;

ja pildid ise salvestatakse kataloogi ./pub/media/catalog/product/x/y/Kus x и y — pildifaili nime esimene ja teine ​​täht. Näiteks fail image.png tuleks salvestada kui ./pub/media/catalog/product/i/m/image.png, et platvorm saaks seda kataloogist toodete kirjeldamisel pildina kasutada.

Registreerumine postitatud ./pub/media/catalog/product/ meediumifail (faili enda paigutamise protsessi selles artiklis ei käsitleta):

function createMediaGallery($imgPathPrefixed)
{
    $attrId = /* get attribute ID by attribute code 'media_gallery' */
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('catalog_product_entity_media_gallery');
    $bind = [
        'attribute_id' => $attrId,
        'value' => $imgPathPrefixed,
        /* 'image' or 'video' */
        'media_type' => 'image',
        'disabled' => false
    ];
    $conn->insert($table, $bind);
    $result = $conn->lastInsertId($table);
    return $result;
}

Registreerimisel määratakse uuele meediumifailile identifikaator.

Seome registreeritud meediumifaili vaikepoe esikülje vastava tootega:

function createGalleryValue($mediaId, $prodId)
{
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('catalog_product_entity_media_gallery_value');
    $bind = [
        'value_id' => $mediaId,
        /* use admin store view by default */
        'store_id' => 0,
        'entity_id' => $prodId,
        'label' => null,
        /* we have one only image */
        'position' => 1,
        'disabled' => false
    ];
    $conn->insert($table, $bind);
}

Seostame registreeritud meediumifaili vastava tootega, ilma et see oleks seotud ühegi poefassaadiga. Pole selge, kus täpselt neid andmeid kasutatakse ja miks eelmise tabeli andmetele ligi ei pääse, kuid see tabel on olemas ja andmed kirjutatakse sinna siis, kui tootele pilt lisatakse. Nii et kõik.

function createGalleryValueToEntity($mediaId, $prodId)
{
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @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

Meediumifaili saab kasutada erinevate rollidega (vastav atribuudikood on märgitud sulgudes):

  • Base(image)
  • Väike pilt (small_image)
  • Pisipilt (thumbnail)
  • Näidispilt (swatch_image)

Rollide linkimine meediumifailiga on täpselt see, mis toimub catalog_product_entity_varchar. Sidumiskood on sarnane koodiga "Toote põhiomadused"

Pärast tootele pildi lisamist administraatoripaneelil näeb see välja järgmine:

Magento 2: importige tooted otse andmebaasi

Kategooria

Peamised tabelid, mis sisaldavad andmeid kategooriate kaupa:

  • catalog_category_entity: kategooriate register;
  • catalog_category_product: seos toodete ja kategooriate vahel;
  • catalog_category_entity_*: EAV atribuudi väärtused;

Algselt sisaldab tühjas Magento rakenduses kategooriaregister 2 kategooriat (lühendasin veergude nimesid: 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 kataloogi juur ja see pole saadaval ei administraatoripaneelil ega esilehel. Kategooria id=2 (Vaikekategooria) on põhisaidi peapoe juurkategooria (Peamine veebisaidi pood), mis luuakse rakenduse juurutamisel (vt. Administraator / Kauplused / Kõik kauplused). Pealegi pole esiküljel saadaval ka poe enda juurkategooria, vaid ainult selle alamkategooriad.

Kuna selle artikli teema on endiselt toodete andmete importimine, siis ei kasuta ma kategooriate loomisel otsest andmebaasi sisenemist, vaid kasutan Magento enda pakutavaid klasse (mudeleid ja hoidlaid). Otsest andmebaasi sisenemist kasutatakse ainult imporditud toote seostamiseks kategooriaga (kategooriale vastatakse selle nimi ja sobitamise käigus leitakse 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 lingi lisamist kategooriatesse "1. kategooria" ja "2. kategooria" näevad toote üksikasjad administraatoripaneelil välja umbes sellised:

Magento 2: importige tooted otse andmebaasi

Täiendavad toimingud

Kui andmete importimine on lõppenud, peate tegema järgmised lisatoimingud.

  • andmete indekseerimine: helistage konsoolis ./bin/magento indexer:reindex;
  • toodete/kategooriate URL-ide taasloomine: saate kasutada laiendit "elgentos/regenerate-catalog-urls«

Tooted administraatoripaneelil pärast lisatoimingute tegemist:

Magento 2: importige tooted otse andmebaasi

ja ees:

Magento 2: importige tooted otse andmebaasi

Kokkuvõte

Sama toodete komplekt (10 tükki), mis eelmises artiklis, imporditakse vähemalt suurusjärgu võrra kiiremini (1 sekund versus 10). Kiiruse täpsemaks hindamiseks on vaja suuremat hulka tooteid – mitusada või veel parem tuhandet. Kuid isegi nii väikese sisendandmete puhul võime järeldada, et Magento pakutavate tööriistade (mudelid ja hoidlad) kasutamine on märkimisväärne (rõhutan - palju!) kiirendada vajaliku funktsionaalsuse väljatöötamist, kuid samal ajal oluliselt (rõhutan - palju!) vähendage andmete andmebaasi jõudmise kiirust.

Selle tulemusena osutus vesi märjaks ja see pole ilmutus. Nüüd on mul aga kood, millega mängida ja ehk jõuda mõne huvitavama järelduseni.

Allikas: www.habr.com