Magento 2: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

В erthygl flaenorol Disgrifiais y broses o fewnforio cynhyrchion i Magento 2 yn y ffordd arferol - trwy fodelau ac ystorfeydd. Mae gan y dull arferol gyflymder prosesu data isel iawn. Roedd fy ngliniadur yn cynhyrchu tua un cynnyrch yr eiliad. Yn y parhad hwn, rwy'n ystyried ffordd amgen o fewnforio cynnyrch - trwy fynediad uniongyrchol i'r gronfa ddata, gan osgoi'r mecanweithiau safonol Magento 2 (modelau, ffatrïoedd, storfeydd). Gellir addasu dilyniant y camau i fewnforio cynhyrchion i unrhyw iaith raglennu a all weithio gyda MySQL.

Ymwadiad: Mae gan Magento ymarferoldeb parod ar gyfer mewnforio data ac, yn fwyaf tebygol, bydd yn ddigon i chi. Fodd bynnag, os oes angen rheolaeth fwy cyflawn arnoch dros y broses fewnforio, heb fod yn gyfyngedig i baratoi ffeil CSV ar gyfer yr hyn sydd gennych, croeso i gath.

Magento 2: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

Gellir gweld y cod sy'n deillio o ysgrifennu'r ddwy erthygl yn y modiwl Magento "fflansiwr32/mage2_ext_demo_import" . Dyma rai cyfyngiadau a ddilynais i symleiddio cod y modiwl demo:

  • Dim ond cynhyrchion sy'n cael eu creu, nid eu diweddaru.
  • Un warws
  • Dim ond enwau categorïau sy'n cael eu mewnforio, heb eu strwythur
  • Mae strwythurau data yn cydymffurfio â fersiwn 2.3

JSON am fewnforio un cynnyrch:

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

Trosolwg o'r prif gamau mewnforio

  • cofrestru'r cynnyrch ei hun
  • cysylltiad rhwng cynnyrch a gwefan
  • priodoleddau cynnyrch sylfaenol (EAV)
  • data rhestr eiddo (swm y cynnyrch mewn stoc)
  • cyfryngau (lluniau)
  • cysylltiad â chategorïau catalog

Cofrestru Cynnyrch

Gellir dod o hyd i wybodaeth sylfaenol am y cynnyrch yn 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`)
)

Y wybodaeth leiaf sydd ei hangen i greu cofnod yn y gofrestr cynnyrch yw:

  • attribute_set_id
  • sku

ychwanegol:

  • type_id — os na fyddwn yn ei nodi, yna defnyddir 'syml'

I ysgrifennu'n uniongyrchol i'r gronfa ddata, rwy'n defnyddio addasydd DB Magento ei hun:

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

Ar ôl cofrestru'r cynnyrch gyda catalog_product_entity mae'n dod yn weladwy yn y panel gweinyddol, yn y grid cynnyrch (Catalog/Cynhyrchion).

Magento 2: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

Perthynas rhwng cynnyrch a gwefan

Mae cysylltiad y cynnyrch â'r wefan yn pennu ym mha storfeydd ac arddangosiadau y bydd y cynnyrch ar gael yn y blaen.

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: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

Priodoleddau cynnyrch sylfaenol

Nid oes gan y cynnyrch sydd newydd ei gofrestru enw na disgrifiad eto. Gwneir hyn i gyd drwodd priodoleddau EAV. Dyma restr o nodweddion cynnyrch sylfaenol sydd eu hangen er mwyn i'r cynnyrch gael ei arddangos yn gywir ar y blaen:

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

Mae priodoledd ar wahân yn cael ei ychwanegu at gynnyrch fel hwn (mae manylion cael y dynodwr a math y priodoledd o'i god wedi'u hepgor):

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

Gan ddefnyddio'r cod priodoledd, rydym yn pennu ei id a'i fath o ddata (datetime, decimal, int, text, varchar), yna ysgrifennwch y data ar gyfer y ffenestr weinyddol i'r tabl priodol (store_id = 0).

Ar ôl ychwanegu'r priodoleddau uchod at y cynnyrch, cewch y llun hwn yn y panel gweinyddol:

Magento 2: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

Data rhestr

Gan ddechrau o fersiwn 2.3 yn Magento, mae dwy set gyfochrog o dablau sy'n darparu storio gwybodaeth rhestr eiddo (maint y cynnyrch):

  • cataloginventory_*: hen strwythur;
  • inventory_*: strwythur newydd (MSI - Rhestr Aml Ffynhonnell);

Mae angen i chi ychwanegu data rhestr eiddo i'r ddau strwythur, oherwydd nid yw'r strwythur newydd eto'n gwbl annibynnol ar yr hen un (mae'n debygol iawn ar gyfer default warws yn y strwythur newydd bwrdd yn cymryd rhan cataloginventory_stock_status fel inventory_stock_1).

rhestr catalog_

Wrth ddefnyddio Magneto 2.3 mae gennym 2 gofnod i mewn i ddechrau store_website, sy'n cyfateb i ddau safle - gweinyddol a phrif gleient:

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

Bwrdd cataloginventory_stock dim ond un cofnod sydd gennym:

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

Hynny yw, dim ond un “warws” sydd yn ein hen strwythur (stock) ac mae'n gysylltiedig â'r wefan weinyddol. Ychwanegu rhai newydd trwy'r panel gweinyddol sources/stocks yn MSI (strwythur newydd) ddim yn arwain at gofnodion newydd yn cataloginventory_stock.

Mae data stocrestr am gynhyrchion yn yr hen strwythur yn cael ei gofnodi i ddechrau mewn tablau:

  • cataloginventory_stock_item
  • cataloginventory_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,
        /* 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);
}

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,
        /* 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);
}

rhestr eiddo_

I ddechrau, mae'r strwythur newydd ar gyfer storio data rhestr eiddo yn cynnwys 1 "ffynhonnell'(inventory_source):

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

ac un"siop'(inventory_stock):

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

«Ffynhonnell» cynrychioli'r storfa ffisegol ar gyfer cynhyrchion (mae'r cofnod yn cynnwys cyfesurynnau ffisegol a chyfeiriad post). "Warws"yn undeb rhesymegol o sawl "ffynhonnell" (inventory_source_stock_link)

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

ar y lefel y mae'r cysylltiad â'r sianel werthu yn digwydd (inventory_stock_sales_channel)

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

A barnu yn ôl y strwythur data, tybir gwahanol fathau o sianeli gwerthu, ond yn ddiofyn dim ond y cysylltiad “stoc"-"wefan"(mae'r ddolen i'r wefan yn dilyn cod y wefan - base).

Un"siop"gellir ei gysylltu â sawl un"ffynonellau"ac un"ffynhonnell" - i sawl un "warysau"(perthynas llawer i lawer). Mae'r eithriadau yn rhagosodedig "ffynhonnell"Ac"siop" . Nid ydynt wedi'u hailgysylltu ag endidau eraill (cyfyngiad ar lefel y cod - y gwall "Methu â chadw dolen sy'n ymwneud â Ffynhonnell Ragosodedig neu Stoc Ragosodedig"). Mae mwy o fanylion am strwythur MSI yn Magento 2 i'w gweld yn yr erthygl “System reoli warws gan ddefnyddio CQRS a Ffynonellau Digwyddiadau. Dylunio".

Byddaf yn defnyddio'r ffurfweddiad diofyn ac yn ychwanegu'r holl wybodaeth rhestr eiddo i'r ffynhonnell default, sy'n ymwneud â'r sianel werthu sy'n gysylltiedig â'r wefan gyda'r cod base (yn cyfateb i ben blaen y storfa - gweler 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);
}

Ar ôl ychwanegu data rhestr eiddo at y cynnyrch yn y panel gweinyddol, byddwch yn cael y llun hwn:

Magento 2: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

Cyfryngau

Wrth ychwanegu delwedd "â llaw" at gynnyrch trwy'r panel gweinyddol, mae'r wybodaeth berthnasol wedi'i nodi yn y tablau canlynol:

  • catalog_product_entity_media_gallery: cofrestrfa cyfryngau (delweddau a ffeiliau fideo);
  • catalog_product_entity_media_gallery_value: cysylltu cyfryngau â chynhyrchion ac arddangosiadau (lleoleiddio);
  • catalog_product_entity_media_gallery_value_to_entity: cysylltu cyfryngau â chynhyrchion yn unig (cynnwys cyfryngau diofyn ar gyfer y cynnyrch yn ôl pob tebyg);
  • catalog_product_entity_varchar: Mae'r rolau y defnyddir y ddelwedd ynddynt yn cael eu storio yma;

ac mae'r delweddau eu hunain yn cael eu cadw i'r cyfeiriadur ./pub/media/catalog/product/x/y/lle x и y — llythrennau cyntaf ac ail lythrennau enw'r ffeil delwedd. Er enghraifft, ffeil image.png dylid ei gadw fel ./pub/media/catalog/product/i/m/image.png, fel y gall y llwyfan ei ddefnyddio fel delwedd wrth ddisgrifio cynhyrchion o'r catalog.

Postiwyd y gofrestr i mewn ./pub/media/catalog/product/ ffeil cyfryngau (nid yw'r broses o osod y ffeil ei hun yn cael ei thrafod yn yr erthygl hon):

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

Ar ôl cofrestru, rhoddir dynodwr i ffeil cyfryngau newydd.

Rydym yn cysylltu'r ffeil cyfryngau cofrestredig â'r cynnyrch cyfatebol ar gyfer blaen y siop rhagosodedig:

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

Rydym yn cysylltu'r ffeil cyfryngau cofrestredig â'r cynnyrch cyfatebol heb fod ynghlwm wrth unrhyw flaen siop. Nid yw'n glir ble yn union y defnyddir y data hwn a pham ei bod yn amhosibl cael mynediad at y data o'r tabl blaenorol, ond mae'r tabl hwn yn bodoli ac ysgrifennir y data ato pan ychwanegir llun at y cynnyrch. Felly dyna ni.

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

Gellir defnyddio ffeil cyfryngau gyda gwahanol rolau (nodir y cod priodoledd cyfatebol mewn cromfachau):

  • sylfaen (image)
  • Delwedd Bach (small_image)
  • Mân-lun (thumbnail)
  • Delwedd Swatch (swatch_image)

Cysylltu rolau â ffeil cyfryngau yw'r union beth sy'n digwydd yn catalog_product_entity_varchar. Mae'r cod rhwymo yn debyg i'r cod yn y "Priodoleddau cynnyrch sylfaenol".

Ar ôl ychwanegu delwedd at y cynnyrch yn y panel gweinyddol mae'n edrych fel hyn:

Magento 2: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

Категории

Prif dablau yn cynnwys data yn ôl categori:

  • catalog_category_entity: cofrestr categorïau;
  • catalog_category_product: cysylltiad rhwng cynhyrchion a chategorïau;
  • catalog_category_entity_*: gwerthoedd priodoledd EAV;

I ddechrau, mewn cais Magento gwag, mae'r gofrestr categorïau yn cynnwys 2 gategori (fe wnes i fyrhau enwau'r colofnau: 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|

Y categori gydag id=1 yw gwraidd catalog cyfan Magento ac nid yw ar gael naill ai yn y panel gweinyddol nac ar y dudalen flaen. Categori gyda id=2 (Categori Rhagosodedig) yw'r categori gwraidd ar gyfer prif storfa'r prif safle (Storfa Prif Wefan) a grëwyd pan fydd y cais yn cael ei ddefnyddio (gweler. Gweinyddol / Storfeydd / Pob Storfa). Ar ben hynny, nid yw categori gwraidd y siop ei hun hefyd ar gael ar y blaen, dim ond ei is-gategorïau.

Gan fod pwnc yr erthygl hon yn dal i fewnforio data ar gynhyrchion, ni fyddaf yn defnyddio mynediad uniongyrchol i'r gronfa ddata wrth greu categorïau, ond byddaf yn defnyddio'r dosbarthiadau a ddarperir gan Magento ei hun (modelau ac ystorfeydd). Defnyddir mynediad uniongyrchol i'r gronfa ddata i gysylltu'r cynnyrch a fewnforiwyd â chategori yn unig (mae'r categori yn cyfateb â'i enw, ac mae'r ID categori yn cael ei adalw wrth ei baru):

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

Ar ôl ychwanegu dolen cynnyrch at y categorïau “Categori 1” a “Categori 2”, mae manylion y cynnyrch yn y panel gweinyddol yn edrych rhywbeth fel hyn:

Magento 2: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

Camau Gweithredu Ychwanegol

Unwaith y bydd y mewnforio data wedi'i gwblhau, mae angen i chi gwblhau'r camau ychwanegol canlynol:

  • mynegeio data: galwch yn y consol ./bin/magento indexer:reindex;
  • adfywio URLs ar gyfer cynhyrchion/categorïau: gallwch ddefnyddio'r estyniad “elgentos/regenerate-catalog-urls«

Cynhyrchion yn y panel gweinyddol ar ôl cyflawni gweithredoedd ychwanegol:

Magento 2: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

ac yn y blaen:

Magento 2: mewnforio cynhyrchion yn uniongyrchol i'r gronfa ddata

Crynodeb

Mae'r un set o gynhyrchion (10 darn) ag yn yr erthygl flaenorol yn cael ei fewnforio o leiaf yn nhrefn maint yn gyflymach (1 eiliad yn erbyn 10). Er mwyn amcangyfrif y cyflymder yn fwy cywir, mae angen nifer fwy o gynhyrchion arnoch chi - rhai cannoedd, neu'n well eto miloedd. Fodd bynnag, hyd yn oed gyda maint mor fach o ddata mewnbwn, gallwn ddod i'r casgliad bod y defnydd o'r offer a ddarperir gan Magento (modelau ac ystorfeydd) yn arwyddocaol (rwy'n pwysleisio - llawer!) cyflymu datblygiad y swyddogaeth ofynnol, ond ar yr un pryd yn sylweddol (rwyf yn pwysleisio - llawer!) lleihau'r cyflymder y mae data yn mynd i mewn i'r gronfa ddata.

O ganlyniad, trodd y dŵr yn wlyb ac nid yw hyn yn ddatguddiad. Fodd bynnag, nawr mae gennyf y cod i chwarae ag ef ac efallai dod i rai casgliadau mwy diddorol.

Ffynhonnell: hab.com