Magento 2: toodete import otse andmebaasi

V eelnevas artiklis Olen kirjeldanud toodete importimise protsessi Magento 2 tavapĂ€rasel viisil — mudelite ja reposte pĂ”hiselt. Tavaline viis erineb oluliselt madala andme töötlemise kiirusest. Minu sĂŒlearvutis saadi umbes ĂŒks toode sekundis. Selles jĂ€tkuteoses kĂ€sitlen alternatiivset toodete importimise meetodit — otse andmebaasi kirjutamine, mööda minnes Magento 2 tavapĂ€rastest mehhanismidest (mudelid, tehased, reposte). Tootete importimise samme saab kohandada igasuguste programmeerimiskeelte jaoks, mis suudavad töötada MySQL-iga.

MĂ€rkus: Magento sisaldab olemasolevat funktsionaalsust andmete importimiseks ja tĂ”enĂ€oliselt piisab teil sellest. Siiski, kui vajate importimisprotsessi ĂŒle rohkem kontrolli, mis ei piirdu ainult CSV-faili ettevalmistamisega tehka — olete teretulnud allapoole.

Magento 2: toodete import otse andmebaasi

Kood, mis tekkis pÀrast mÔlema artikli kirjutamist, on saadaval Magento moodulis «flancer32/mage2_ext_demo_import«. Siin on mÔned piirangud, mida olen jÀrginud, et lihtsustada demo mooduli koodi:

  • Tooted loodetakse ainult, mitte uuendatakse.
  • Üks ladu
  • Importitakse ainult kategooriate nimed, ilma nende struktuurita
  • Andmestruktuurid vastavad versioonile 2.3

JSON ĂŒksiku toote importimiseks:

{
  "sku": "MVA20D-UBV-3",
  "name": "VBA47-29 IEK tihend",
  "desc": "LigipÀÀsu tagamine seadmetele ...",
  "desc_short": "VBA47-29 IEK tihend on mÔeldud ...",
  "price": 5.00,
  "qty": 25,
  "categories": ["Kategooria 1", "Kategooria 2"],
  "image_path": "mva20d_ubv_3.png"
}

Peamiste importimise sammude ĂŒlevaade

  • toote registreerimine
  • toote ja veebisaidi seos
  • toote pĂ”hiatribuutid (EAV)
  • laoseisud (toote kogus laos)
  • meedia (pildid)
  • seos katalooge kategooriatega

Toote 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`)
)

Minimaalne vajalik teave toote registrisse kandmiseks:

  • attribute_set_id
  • sku

tÀiendav:

  • type_id — kui me ei mĂ€rgi, kasutatakse 'simple'

Otsese andmekirje tegemiseks kasutan Magento 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 on see catalog_product_entity nÀhtav administraatoris toote gridis (Kataloog / Tooted).

Magento 2: toodete import otse andmebaasi

Toote ja veebisaidi seos

Toote ja saidi seos mÀÀrab, millistes poodides ja mis vitriinidel toode front-end'is 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: toodete import otse andmebaasi

Toote pÔhijooned

Hiljuti registreeritud tootel pole veel ei nime ega kirjeldust. KÔik see tehakse lÀbi EAV-atribuutid. Siin on loetelu pÔhjatootest, mis on vajalik toote piisavaks kuvamiseks esiplaanil:

  • name
  • price
  • description
  • lĂŒhikirjeldus
  • status
  • maksu_klass_id
  • url_vĂ”ti
  • nĂ€htavus

Tootele lisatakse eraldi atribuut jĂ€rgmiselt (ĂŒksikasjad atribuudikoodi kaudu ID ja tĂŒĂŒbi saamiseks on jĂ€etud vahele):

public function create($prodId, $attrCode, $attrValue)
{
    $attrId = /* saada atribuud ID atribuudikoodi kaudu */
    $attrType = /* saada atribuuditĂŒĂŒp [datetime|decimal|int|text|varchar] atribuudikoodi kaudu */
    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,
            /* pane kÔik atribuudid vaikepoe vaatesse id=0 (admin) */
            'store_id' => 0,
            'value' => $attrValue
        ];
        $conn->insert($table, $bind);
    }
}

Atribuudikoodi kaudu mÀÀrame selle ID ja andmetĂŒĂŒbi (datetime, decimal, int, text, varchar), seejĂ€rel kirjutame vastavatesse tabelitesse andmed halduskatalooge (store_id = 0).

PÀrast eeltoodud atribuudide lisamist tootese saadakse administraatorikeskkonnas jÀrgmine pilt:

Magento 2: toodete import otse andmebaasi

Laoseisu andmed

Alates versioonist 2.3 eksisteerib Magento-s paralleelselt kaks tabelisarja, mis tagavad inventariteabe (toote kogus) sÀilimise:

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

Inventariandmeid tuleb lisada mÔlemasse struktuuri, kuna uus struktuur ei ole veel tÀielikult vana struktuurist sÔltumatu (tundub, et uue struktuuri puhul on varude kohta kasutusel tabel default cataloginventory_stock_status inventory_stock_1 kui cataloginventory_).

Magneto 2.3 juurutamisel on meil algselt 2 kirjet tabelis

store_website , mis vastab kahele veebisaidile — halduri ja peamise kliendi:website_id|code |name |sort_order|default_group_id|is_default| ----------|-----|------------|----------|----------------|----------| 0|admin|Admin | 0| 0| 0| 1|base |Main Website| 0| 1| 1|

Tabelis

cataloginventory_stock on meil ainult ĂŒks kirje: stock_id|website_id|stock_name| --------|----------|----------| 1| 0|Default |

Seega on meie vanas struktuuris ainult ĂŒks „lao“ (

stock) ja see on seotud halduri veebisaidiga. Uutestocks sources/lisamine MSI-sse (uus struktuur) ei too kaasa uute kirjete tekke. MSI (uus struktuur) ei too kaasa uute kirjete tekkimist on meil ainult ĂŒks kirje:.

Toote varude andmed vanas struktuuris on algselt mÀÀratud tabelites:

  • cataloginventory_stock_item
  • inventory_stock_1

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 'cataloginventory' struktuuris vaikimisi ĂŒhte varu */
        'stock_id' => 1,
        'qty' => $qty,
        'is_qty_decimal' => $isQtyDecimal,
        'is_in_stock' => $isInStock,
        /* vaikesaldo on seotud administraatori veebisaidiga (vt `cataloginventory_stock`) */
        'website_id' => 0
    ];
    $conn->insert($table, $bind);
}

inventory_stock_1

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 'cataloginventory' struktuuris vaikimisi ĂŒhte varu */
        'stock_id' => 1, 
        'qty' => $qty,
        'stock_status' => MagentoCatalogInventoryApiDataStockStatusInterface::STATUS_IN_STOCK,
        /* vaikesaldo on seotud administraatori veebisaidiga (vt `cataloginventory_stock`) */
        'website_id' => 0 
    ];
    $conn->insert($table, $bind);
}

inventory_

Alguses uus struktuur inventaride andmete hoidmiseks sisaldab 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 «lao» (inventory_stock):

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

«Allikas» on fĂŒĂŒsiline ladustamisruum toodete jaoks (salvestus sisaldab fĂŒĂŒsilisi koordinaate ja aadressi). «Ladu» on loogiline ĂŒhendus mitme «allika» vahel (inventory_source_stock_link)

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

mille tasandil toimub sidumine mĂŒĂŒgikanaliga (inventory_stock_sales_channel)

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

Andmestruktuuri pĂ”hjal on eeldatavad erinevad mĂŒĂŒgikanali tĂŒĂŒbid, kuid vaikimisi kasutatakse ainult seost «) ja see on seotud halduri veebisaidiga. Uute«-«website» (link veebisaidile lĂ€heb lĂ€bi veebisaidi koodi — base).

Üks «lao» vĂ”ib olla seotud mitme «allika«, ja ĂŒks «allikas» — mitme «ladude» (suhe «palju-palju»). Erandid on vaikimisi «allikas» ja «lao«. Neid ei saa teistele ĂŒksustele uuesti siduda (kooditasemel piirang — viskab vea «Cannot save link related to Default Source or Default Stock«). Magento 2 MSI struktuuriga saab lĂ€hemalt tutvuda artiklis «LaoseisuhaldussĂŒsteem CQRS ja Event Sourcing abil. Projekteerimine«.

Kasutan vaikimisi seadistust ja lisan kogu laoseisu teabe allikale default, mis on seotud mĂŒĂŒgikanaliga, mis on seotud veebisaidiga, millel on kood base (vastab poe kliendipoolsele osale — vt. , mis vastab kahele veebisaidile — halduri ja peamise kliendi:):

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 tooteseadetesse adminpaneelis on tulemuseks jÀrgmine pilt:

Magento 2: toodete import otse andmebaasi

Meedia

KÀsitsi toote juurde piltide lisamisel adminpaneelis kantakse vastav teave jÀrgmisesse tabelitesse:

  • catalog_product_entity_media_gallery: meedia registris (pildid ja videotoad);
  • catalog_product_entity_media_gallery_value: meedia sidumine toodete ja vitriinide (lokaliseerimine);
  • catalog_product_entity_media_gallery_value_to_entity: meedia sidumine ainult toodetega (eeldatavasti toote vaikimisi meediakuidas);
  • catalog_product_entity_varchar: siin salvestatakse rollid, kus kuvatakse pilt;

ja pildid ise salvestatakse katalooge ./pub/media/catalog/product/x/y/, kus x ja y — pildi faili nime esimesed kaks tĂ€hte. NĂ€iteks peab fail image.png olema salvestatud kui ./pub/media/catalog/product/i/m/image.png, et platvorm saaks seda kasutada pildina, kui kirjeldada katalooge tooteid.

Registreerime paigutatud ./pub/media/catalog/product/ meediafail (faili paigutamise protsessi antud 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;
}

Uue meediafaili registreerimisel antakse sellele identifikaator.

Seome registreeritud meediafaili vastava tootega vaikimisi kaupluses:

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

Seome registreeritud meediafaili sidumine vastava tootega, ilma et see oleks seotud mÔne kaupluse kuvandiga. Pole selge, kus tÀpselt neid andmeid kasutatakse ja miks ei saa kasutada eelmist tabelit, kuid see tabel eksisteerib ja andmeid kirjutatakse sinna, kui pilt tootele lisatakse. Seega on asi nii.

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

Meediafaili saab kasutada erinevate rollidega (sulgudes on vastava atribuudi kood):

  • PĂ”hikomponent (pilt)
  • VĂ€ike pilt (small_image)
  • Kujutis (thumbnail)
  • Proovikuju pilt (swatch_image)

Rollide seondamine meediafailiga toimub siin catalog_product_entity_varchar. Seondumise kood sarnaneb koodiga jaotises «Toote pÔhijooned«.

PÀrast toote juurde pildi lisamist admin paneelis nÀeb see vÀlja jÀrgmiselt:

Magento 2: toodete import otse andmebaasi

Kategooriad

Peamised tabelid, kus on andmed kategooriate kohta:

  • catalog_category_entity: kategooriate register;
  • catalog_category_product: toodete ja kategooriate seos;
  • catalog_category_entity_*: EAV-atribuutide vÀÀrtused;

Alguses, tĂŒhjas Magento rakenduses on kategooriate registris 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-katalooge juur ja pole admin paneelis ega eespool saadaval. Kategooria id=2 (Vaikimisi kategooria) on peamise poe juurkategooria peamise saidi (Peamine veebisaidi pood), mis luuakse rakenduse juurutamisel (vt. Admin / Kauplused / KÔik kauplused). TÔepoolest, poe juurkategooria ees ei ole samuti saadaval, ainult selle alamkategooriad.

Kuna selle artikli teema on andmete importimine toodete osas, ei kasuta ma kategooriate loomisel otse andmebaasi kirjutamist, vaid kasutan Magento poolt pakutavaid klasse (mudeleid ja hoidlaid). Otsene andmebaasi kirjutamine toimub ainult imporditud toote sidumiseks kategooriaga (kategooria sidumine toimub selle nime jÀrgi, sidumisel 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 sidumist kategooriatega „Kategooria 1” ja „Kategooria 2” nĂ€evad toote detailid administraatori paneelis vĂ€lja umbes nii:

Magento 2: toodete import otse andmebaasi

Lisategevused

Andmete importimise lÔpetamisel tuleb teha jÀrgmised lisategevused:

  • andmete indeksimine: kutse konsoolis ./bin/magento indexer:reindex;
  • toodete/kategooriate URL-ide regeneratsioon: saab kasutada laiendust „elgentos/regenerate-catalog-urls«

Tooted administraatori paneelis pÀrast lisategevuste tegemist:

Magento 2: toodete import otse andmebaasi

ja esimeses:

Magento 2: toodete import otse andmebaasi

KokkuvÔte

Sama toodete komplekt (10 tĂŒkki), mis oli eelmises artiklis, imporditakse vĂ€hemalt kordades kiiremini (1 sekund vĂ”rreldes 10). TĂ€psema kiirusanalĂŒĂŒsi jaoks on vajalik suurem tootekogus — paar sada, veel parem kui tuhat. Sellegipoolest, isegi sellise vĂ€ikese sisendi korral saab jĂ€reldada, et Magento poolt pakutud tööriistade (mudelid ja repod) kasutamine kiirendab oluliselt (rĂ”hutan — oluliselt!) nĂ”utava funktsionaalsuse arendust, kuid samas vĂ€hendab mĂ€rgatavalt (rĂ”hutan — oluliselt!) andmete jĂ”udmise kiirus andmebaasi.

KokkuvĂ”ttes, vesi on niiske, ja see pole mingi avastus. Sellegipoolest on mul nĂŒĂŒd kood, millega edasi mĂ€ngida ja vĂ”ib-olla teha huvitavamaid jĂ€reldusi.

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster