Magento 2: flytja vörur beint inn í gagnagrunninn

В Fyrri grein Ég lýsti ferlinu við að flytja vörur inn í Magento 2 á venjulegan hátt - í gegnum líkön og geymslur. Venjuleg aðferð hefur mjög lágan gagnavinnsluhraða. Fartölvan mín framleiddi um eina vöru á sekúndu. Í þessu framhaldi íhuga ég aðra leið til að flytja inn vöru - með því að fara beint inn í gagnagrunninn, framhjá stöðluðum Magento 2 aðferðum (líkön, verksmiðjur, geymslur). Röð skrefa til að flytja inn vörur er hægt að aðlaga að hvaða forritunarmáli sem er sem getur unnið með MySQL.

Afneitun ábyrgðar: Magento hefur tilbúna virkni fyrir gagnainnflutningur og líklega mun það vera nóg fyrir þig. Hins vegar, ef þú þarft fullkomnari stjórn á innflutningsferlinu, ekki takmarkað við að útbúa CSV skrá fyrir það sem þú hefur, velkomið að kötta.

Magento 2: flytja vörur beint inn í gagnagrunninn

Kóðann sem verður til við að skrifa báðar greinarnar er hægt að skoða í Magento einingunni "flancer32/mage2_ext_demo_import". Hér eru nokkrar takmarkanir sem ég fylgdi til að einfalda kynningareiningakóðann:

  • Vörur eru aðeins búnar til, ekki uppfærðar.
  • Eitt vöruhús
  • Aðeins flokkaheiti eru flutt inn, án uppbyggingar þeirra
  • Gagnauppbygging er í samræmi við útgáfu 2.3

JSON fyrir innflutning á einni vöru:

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

Yfirlit yfir helstu stig innflutnings

  • skráningu vörunnar sjálfrar
  • tengingu á milli vöru og vefsíðu
  • grunneiginleika vöru (EAV)
  • birgðagögn (magn vöru á lager)
  • fjölmiðlar (myndir)
  • tengingu við vörulistaflokka

Vöruskráning

Grunnupplýsingar um vörur má finna í 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`)
)

Lágmarksupplýsingarnar sem þarf til að búa til færslu í vöruskránni eru:

  • attribute_set_id
  • sku

viðbótar:

  • type_id - ef við tilgreinum það ekki, þá verður 'einfalt' notað

Til að skrifa beint í gagnagrunninn nota ég DB millistykki Magento sjálfs:

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

Eftir að hafa skráð vöruna hjá catalog_product_entity það verður sýnilegt á stjórnborðinu, í vörunetinu (Vörulisti/vörur).

Magento 2: flytja vörur beint inn í gagnagrunninn

Tengsl vöru og vefsíðu

Tenging vörunnar við síðuna ræður því í hvaða verslunum og sýningum varan verður fáanleg að framan.

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: flytja vörur beint inn í gagnagrunninn

Grunneiginleikar vöru

Nýskráð vara hefur ekki enn nafn eða lýsingu. Allt er þetta gert í gegn EAV eiginleikar. Hér er listi yfir helstu vörueiginleika sem þarf til þess að varan sé rétt birt að framan:

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

Sérstakri eiginleiki er bætt við vöru eins og þessa (upplýsingum um að fá auðkenni og gerð eigindarinnar úr kóða hennar er sleppt):

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

Með því að nota eiginleikakóðann ákveðum við auðkenni hans og gagnategund (datetime, decimal, int, text, varchar), skrifaðu síðan gögnin fyrir stjórnunargluggann í viðeigandi töflu (store_id = 0).

Eftir að ofangreindum eiginleikum hefur verið bætt við vöruna færðu þessa mynd á stjórnborðinu:

Magento 2: flytja vörur beint inn í gagnagrunninn

Birgðagögn

Frá og með útgáfu 2.3 í Magento eru tvö samhliða sett af töflum sem veita geymslu á birgðaupplýsingum (vörumagn):

  • cataloginventory_*: gamalt mannvirki;
  • inventory_*: ný uppbygging (MSI - Multi Source Inventory);

Þú þarft að bæta birgðagögnum við bæði mannvirkin, vegna þess að nýja skipulagið er enn ekki alveg óháð því gamla (það er mjög líklegt að fyrir default vöruhús í nýju skipulagi borð er að ræða cataloginventory_stock_status sem inventory_stock_1).

vörulista_

Þegar Magneto 2.3 er dreift höfum við upphaflega 2 færslur inn store_website, sem samsvarar tveimur stöðum - stjórnunar- og aðalviðskiptavinur:

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

Tafla cataloginventory_stock við höfum aðeins eina færslu:

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

Það er, í gamla skipulaginu okkar er aðeins eitt „vöruhús“ (stock) og það er tengt við stjórnsýsluvefinn. Að bæta við nýjum í gegnum stjórnborðið sources/stocks í MSI (nýtt skipulag) leiðir ekki af sér nýjar færslur í cataloginventory_stock.

Birgðagögn um vörur í gamla skipulaginu eru upphaflega skráð í töflur:

  • cataloginventory_stock_item
  • cataloginventory_stock_status

vörulistabirgðabirgðavara

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

verslunarbirgðastaða

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

birgðahald_

Upphaflega inniheldur nýja uppbyggingin til að geyma birgðagögn 1 "uppspretta"(inventory_source):

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

og einn"vörugeymsla"(inventory_stock):

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

«Source» táknar líkamlega geymslu fyrir vörur (skráin inniheldur líkamleg hnit og póstfang). "Vörugeymsla"er rökrétt sameining nokkurra "heimilda" (inventory_source_stock_link)

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

á því stigi sem tengingin við sölurásina á sér stað (inventory_stock_sales_channel)

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

Miðað við gagnauppbyggingu er gert ráð fyrir ýmsum tegundum söluleiða, en sjálfgefið er aðeins tengingin “lager"-"vefsíðu."(tengillinn á vefsíðuna fylgir vefsíðukóðanum - base).

Einn"vörugeymsla"hægt að tengja við nokkra"heimildir"og einn"uppspretta"- til nokkurra"vöruhús"(margir-til-margir samband). Undantekningarnar eru sjálfgefnar "uppspretta"Og"vörugeymsla". Þeir eru ekki tengdir aftur við aðra aðila (takmörkun á kóðastigi - villa "Ekki er hægt að vista tengil sem tengist sjálfgefnum uppruna eða sjálfgefnu lager"). Frekari upplýsingar um MSI uppbygginguna í Magento 2 er að finna í greininni “Vöruhússtjórnunarkerfi sem notar CQRS og Event Sourcing. Hönnun".

Ég mun nota sjálfgefna stillingu og bæta öllum birgðaupplýsingum við upprunann default, sem tekur þátt í sölurásinni sem tengist vefsíðunni með kóðanum base (svarar til framenda verslunarinnar - sjá 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);
}

Eftir að hafa bætt birgðagögnum við vöruna á stjórnborðinu færðu þessa mynd:

Magento 2: flytja vörur beint inn í gagnagrunninn

Fjölmiðlar

Þegar mynd er „handvirkt“ bætt við vöru í gegnum stjórnborðið eru viðeigandi upplýsingar skrifaðar niður í eftirfarandi töflur:

  • catalog_product_entity_media_gallery: fjölmiðlaskrá (myndir og myndbandsskrár);
  • catalog_product_entity_media_gallery_value: tengja fjölmiðla við vörur og sýningarskápa (staðsetning);
  • catalog_product_entity_media_gallery_value_to_entity: að tengja miðil eingöngu við vörur (væntanlega sjálfgefið efni fyrir vöruna);
  • catalog_product_entity_varchar: Hlutverkin sem myndin er notuð í eru geymd hér;

og myndirnar sjálfar eru vistaðar í möppunni ./pub/media/catalog/product/x/y/hvar x и y — fyrsti og annar stafur í nafni myndskrár. Til dæmis, skrá image.png ætti að vista sem ./pub/media/catalog/product/i/m/image.png, svo að pallurinn geti notað hann sem mynd þegar vörum úr vörulistanum er lýst.

Skráning sett inn ./pub/media/catalog/product/ fjölmiðlaskrá (ekki er fjallað um ferlið við að setja skrána sjálft í þessari grein):

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

Við skráningu fær nýr miðlunarskrá úthlutað auðkenni.

Við tengjum skráða miðlunarskrá við samsvarandi vöru fyrir sjálfgefna verslunargluggann:

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

Við tengjum skráða fjölmiðlaskrá við samsvarandi vöru án þess að vera bundin við neina verslunarglugga. Ekki er ljóst hvar nákvæmlega þessi gögn eru notuð og hvers vegna ómögulegt er að nálgast gögnin úr fyrri töflu, en þessi tafla er til og gögnin eru skrifuð á hana þegar mynd er bætt við vöruna. Svo það er það.

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

Hægt er að nota miðlunarskrá með mismunandi hlutverkum (samsvarandi eigindarkóði er tilgreindur innan sviga):

  • Grunnur (image)
  • Lítil mynd (small_image)
  • Smámynd (thumbnail)
  • Swatch mynd (swatch_image)

Að tengja hlutverk við miðlunarskrá er nákvæmlega það sem gerist í catalog_product_entity_varchar. Bindarkóðinn er svipaður og kóðann í "Grunneiginleikar vöru".

Eftir að mynd hefur verið bætt við vöruna á stjórnborðinu lítur það svona út:

Magento 2: flytja vörur beint inn í gagnagrunninn

Категории

Aðaltöflur sem innihalda gögn eftir flokkum:

  • catalog_category_entity: flokkaskrá;
  • catalog_category_product: tenging milli vara og flokka;
  • catalog_category_entity_*: EAV eigindargildi;

Upphaflega, í tómu Magento forriti, inniheldur flokkaskráin 2 flokka (ég stytti dálknöfnin: 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|

Flokkurinn með id=1 er rót alls Magento vörulistans og er hvorki fáanlegur á stjórnborðinu né á forsíðunni. Flokkur með id=2 (Öðruvísi dagur) er rótarflokkurinn fyrir aðalverslun aðalsíðunnar (Aðal vefverslun) búin til þegar forritið er sett í notkun (sjá. Stjórnandi / Verslanir / Allar verslanir). Þar að auki er rótarflokkur verslunarinnar sjálfrar heldur ekki fáanlegur að framan, aðeins undirflokkar hennar.

Þar sem efni þessarar greinar er enn að flytja inn gögn um vörur, mun ég ekki nota beina færslu inn í gagnagrunninn við að búa til flokka, heldur mun ég nota flokka sem Magento gefur sjálft (líkön og geymslur). Bein færsla inn í gagnagrunninn er aðeins notuð til að tengja innfluttu vöruna við flokk (flokknum er samsvarað með nafni hans og flokkaauðkenni er sótt við pörun):

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

Eftir að vörutengli hefur verið bætt við flokkana „Flokkur 1“ og „Flokkur 2“ líta vöruupplýsingarnar á stjórnborðinu einhvern veginn svona út:

Magento 2: flytja vörur beint inn í gagnagrunninn

Viðbótaraðgerðir

Þegar gagnainnflutningi er lokið þarftu að ljúka eftirfarandi viðbótarskrefum:

  • gagnaskráning: hringdu í stjórnborðið ./bin/magento indexer:reindex;
  • endurnýjun vefslóða fyrir vörur/flokka: þú getur notað viðbótina "elgentos/regenerate-catalog-urls«

Vörur á stjórnborðinu eftir að hafa framkvæmt viðbótaraðgerðir:

Magento 2: flytja vörur beint inn í gagnagrunninn

og að framan:

Magento 2: flytja vörur beint inn í gagnagrunninn

Yfirlit

Sama sett af vörum (10 stykki) og í fyrri grein er flutt inn að minnsta kosti stærðargráðu hraðar (1 sekúnda á móti 10). Til að meta hraðann nákvæmari þarftu fleiri vörur - nokkur hundruð, eða jafnvel þúsundir. Hins vegar, jafnvel með svo litlum inntaksgögnum, getum við ályktað að notkun tækjanna sem Magento býður upp á (líkön og geymslur) sé mikilvæg (ég legg áherslu á - mikið!) flýta fyrir þróun nauðsynlegrar virkni, en á sama tíma verulega (ég legg áherslu á - mikið!) draga úr hraðanum sem gögn komast inn í gagnagrunninn.

Í kjölfarið reyndist vatnið blautt og er ekki um opinberun að ræða. Hins vegar hef ég nú kóðann til að leika mér með og kannski kemst ég að áhugaverðari niðurstöðum.

Heimild: www.habr.com