Magento 2. ներմուծել ապրանքներ անմիջապես տվյալների բազա

В նախորդ հոդվածը Ես նկարագրեցի Magento 2 ապրանքների ներմուծման գործընթացը սովորական ձևով՝ մոդելների և պահեստների միջոցով: Սովորական մեթոդն ունի տվյալների մշակման շատ ցածր արագություն: Իմ նոութբուքը վայրկյանում մոտավորապես մեկ ապրանք էր արտադրում: Այս շարունակության մեջ դիտարկում եմ ապրանքի ներմուծման այլընտրանքային տարբերակ՝ ուղղակի մուտքագրելով տվյալների բազա՝ շրջանցելով ստանդարտ Magento 2 մեխանիզմները (մոդելներ, գործարաններ, պահեստներ)։ Ապրանքների ներմուծման քայլերի հաջորդականությունը կարող է հարմարեցվել ցանկացած ծրագրավորման լեզվին, որը կարող է աշխատել MySQL-ի հետ:

Հրաժարում պատասխանատվությունիցMagento-ն ունի պատրաստի ֆունկցիոնալություն տվյալների ներմուծում և, ամենայն հավանականությամբ, դա ձեզ կբավականացնի։ Այնուամենայնիվ, եթե ձեզ անհրաժեշտ է ավելի ամբողջական վերահսկողություն ներմուծման գործընթացի վրա, չսահմանափակվելով ձեր ունեցածի համար CSV ֆայլ պատրաստելով, բարի գալուստ cat:

Magento 2. ներմուծել ապրանքներ անմիջապես տվյալների բազա

Երկու հոդվածները գրելուց ստացված կոդը կարելի է դիտել Magento մոդուլում:flancer32/mage2_ext_demo_import«. Ահա մի քանի սահմանափակումներ, որոնք ես հետևեցի դեմո մոդուլի կոդը պարզեցնելու համար.

  • Ապրանքները միայն ստեղծվում են, չեն թարմացվում:
  • Մեկ պահեստ
  • Ներմուծվում են միայն կատեգորիաների անվանումները՝ առանց դրանց կառուցվածքի
  • Տվյալների կառուցվածքները համապատասխանում են 2.3 տարբերակին

JSON մեկ ապրանք ներմուծելու համար.

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

Ներմուծման հիմնական փուլերի ակնարկ

  • ինքնին ապրանքի գրանցում
  • կապ ապրանքի և կայքի միջև
  • արտադրանքի հիմնական հատկանիշները (EAV)
  • գույքագրման տվյալներ (պահեստում գտնվող ապրանքի քանակը)
  • լրատվամիջոցներ (նկարներ)
  • կապ կատալոգի կատեգորիաների հետ

Ապրանքի գրանցում

Ապրանքի հիմնական տեղեկատվությունը կարելի է գտնել այստեղ 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`)
)

Ապրանքի ռեեստրում գրառում ստեղծելու համար պահանջվող նվազագույն տեղեկատվությունը հետևյալն է.

  • attribute_set_id
  • sku

լրացուցիչ:

  • type_id — եթե մենք դա չնշենք, ապա կօգտագործվի «պարզ»:

Տվյալների բազայում ուղղակիորեն գրելու համար ես օգտագործում եմ հենց Magento-ի DB ադապտեր.

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

Ապրանքը գրանցելուց հետո catalog_product_entity այն տեսանելի է դառնում ադմինիստրատորի վահանակում, արտադրանքի ցանցում (Կատալոգ / Ապրանքներ).

Magento 2. ներմուծել ապրանքներ անմիջապես տվյալների բազա

Ապրանքի և կայքի փոխհարաբերությունները

Ապրանքի կապը կայքի հետ որոշում է, թե որ խանութներում և ցուցադրություններում ապրանքը հասանելի կլինի առջևում:

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. ներմուծել ապրանքներ անմիջապես տվյալների բազա

Ապրանքի հիմնական հատկանիշները

Նոր գրանցված ապրանքը դեռ անուն կամ նկարագրություն չունի։ Այս ամենը կատարվում է միջոցով EAV հատկանիշներ. Ահա հիմնական ապրանքի ատրիբուտների ցանկը, որոնք անհրաժեշտ են, որպեսզի ապրանքը ճիշտ ցուցադրվի առջևում.

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

Առանձին հատկանիշ ավելացվում է նման արտադրանքին (նրա կոդից հատկանիշի նույնացուցիչը և տեսակը ստանալու մանրամասները բաց են թողնվել).

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

Օգտագործելով հատկանիշի կոդը, մենք որոշում ենք դրա ID-ն և տվյալների տեսակը (datetime, decimal, int, text, varchar), ապա գրեք ադմինիստրատիվ պատուհանի տվյալները համապատասխան աղյուսակում (store_id = 0).

Ապրանքին վերը նշված հատկանիշները ավելացնելուց հետո ադմինիստրատորի վահանակում ստանում եք այս նկարը.

Magento 2. ներմուծել ապրանքներ անմիջապես տվյալների բազա

Գույքագրման տվյալներ

Magento-ում 2.3 տարբերակից սկսած՝ կան աղյուսակների երկու զուգահեռ խմբեր, որոնք ապահովում են գույքագրման տեղեկատվության պահպանում (ապրանքի քանակ).

  • cataloginventory_*հին կառուցվածքը;
  • inventory_*նոր կառուցվածք (MSI - Multi Source Inventory);

Երկու կառույցներին էլ պետք է ավելացնեք գույքագրման տվյալները, քանի որ նոր կառույցը դեռ լիովին անկախ չէ հինից (շատ հավանական է, որ համար default պահեստ նոր կառույցում ներառված է սեղան cataloginventory_stock_status ինչպես inventory_stock_1).

կատալոգի գույքագրում_

Magneto 2.3-ը տեղակայելիս սկզբում 2 մուտք ունենք store_website, որը համապատասխանում է երկու կայքի՝ վարչական և հիմնական հաճախորդին.

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

Աղյուսակ cataloginventory_stock մենք ունենք միայն մեկ մուտք.

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

Այսինքն, մեր հին կառույցում կա միայն մեկ «պահեստ» (stock) և այն կապված է վարչական կայքի հետ: Նորերի ավելացում ադմինիստրատորի վահանակի միջոցով sources/stocks MSI-ում (նոր կառուցվածք) չի հանգեցնում նոր մուտքերի cataloginventory_stock.

Հին կառուցվածքի ապրանքների մասին գույքագրման տվյալները սկզբնապես գրանցվում են աղյուսակներում.

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

գույքագրում_

Սկզբում գույքագրման տվյալների պահպանման նոր կառուցվածքը պարունակում է 1 «աղբյուր«(inventory_source):

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

և մեկ»պահեստ«(inventory_stock):

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

«Աղբյուր» ներկայացնում է արտադրանքի ֆիզիկական պահեստը (գրառումը պարունակում է ֆիզիկական կոորդինատներ և փոստային հասցե): «Склад«մի քանի «աղբյուրների» տրամաբանական միավորում է (inventory_source_stock_link)

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

այն մակարդակում, որով տեղի է ունենում կապը վաճառքի ալիքին (inventory_stock_sales_channel)

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

Դատելով տվյալների կառուցվածքից, ենթադրվում են տարբեր տեսակի վաճառքի ուղիներ, բայց լռելյայն միայն կապը «արգանակ«-»կայքը«(կայքի հղումը հետևում է կայքի կոդին. base).

Մեկը"պահեստ«կարելի է կապվել մի քանիսի հետ»աղբյուրները«և մեկ»աղբյուր«- մի քանիսին»պահեստներ«(շատ-շատ հարաբերություններ): Բացառությունները լռելյայն են»աղբյուր"Եւ"պահեստ«. Նրանք կրկին կապված չեն այլ սուբյեկտների հետ (սահմանափակում կոդի մակարդակում՝ սխալ «Հնարավոր չէ պահպանել լռելյայն աղբյուրի կամ կանխադրված բաժնետոմսի հետ կապված հղումը»): Magento 2-ում MSI կառուցվածքի մասին ավելի շատ մանրամասներ կարելի է գտնել հոդվածում «Պահեստի կառավարման համակարգ՝ օգտագործելով CQRS և Event Sourcing: Դիզայն»:

Ես կօգտագործեմ լռելյայն կոնֆիգուրացիան և կավելացնեմ ամբողջ գույքագրման տեղեկատվությունը աղբյուրին default, որը ներգրավված է կոդով կայքի հետ կապված վաճառքի ալիքում base (համապատասխանում է խանութի ճակատային մասին - տես 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);
}

Ադմինիստրատորի վահանակում ապրանքի գույքագրման տվյալները ավելացնելուց հետո դուք ստանում եք այս նկարը.

Magento 2. ներմուծել ապրանքներ անմիջապես տվյալների բազա

ԶԼՄ-ներ

Ադմինիստրատորի վահանակի միջոցով ապրանքին պատկեր «ձեռքով» ավելացնելիս համապատասխան տեղեկատվությունը գրվում է հետևյալ աղյուսակներում.

  • catalog_product_entity_media_galleryմեդիա ռեեստր (պատկերներ և վիդեո ֆայլեր);
  • catalog_product_entity_media_gallery_valueԶԼՄ-ների կապում ապրանքների և ցուցադրությունների հետ (տեղայնացում);
  • catalog_product_entity_media_gallery_value_to_entityմեդիա կապը միայն ապրանքների հետ (ենթադրաբար արտադրանքի համար լռելյայն մեդիա բովանդակություն);
  • catalog_product_entity_varcharԴերերը, որոնցում օգտագործվում է պատկերը, պահվում են այստեղ.

իսկ պատկերներն իրենք պահվում են գրացուցակում ./pub/media/catalog/product/x/y/Որտեղ x и y — պատկերի ֆայլի անվան առաջին և երկրորդ տառերը: Օրինակ՝ ֆայլ image.png պետք է պահպանվի որպես ./pub/media/catalog/product/i/m/image.png, որպեսզի հարթակը կարողանա օգտագործել այն որպես պատկեր կատալոգից ապրանքները նկարագրելիս։

Գրանցվել տեղադրված է ./pub/media/catalog/product/ մեդիա ֆայլ (ֆայլի տեղադրման գործընթացը ինքնին չի քննարկվում այս հոդվածում).

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

Գրանցվելիս նոր մեդիա ֆայլին հատկացվում է նույնացուցիչ:

Մենք գրանցված մեդիա ֆայլը կապում ենք լռելյայն խանութի համապատասխան արտադրանքի հետ.

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

Մենք գրանցված մեդիա ֆայլը կապում ենք համապատասխան ապրանքի հետ՝ առանց որևէ խանութի ցուցափեղկի կապվելու: Պարզ չէ, թե կոնկրետ որտեղ են օգտագործվում այս տվյալները և ինչու անհնար է մուտք գործել նախորդ աղյուսակի տվյալները, բայց այս աղյուսակը գոյություն ունի, և տվյալները գրվում են դրա վրա, երբ նկարն ավելացվում է արտադրանքին: Ուրեմն վերջ:

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

Մեդիա ֆայլը կարող է օգտագործվել տարբեր դերերով (փակագծերում նշված է համապատասխան հատկանիշի կոդը).

  • Հիմք (image)
  • Փոքր պատկեր (small_image)
  • Մանրապատկեր (thumbnail)
  • Swatch Image (swatch_image)

Դերերը մեդիա ֆայլին կապելը հենց այն է, ինչ տեղի է ունենում ներսում catalog_product_entity_varchar. Պարտադիր ծածկագիրը նման է կոդի «Ապրանքի հիմնական հատկանիշները»:

Ադմինիստրատորի վահանակում ապրանքին պատկեր ավելացնելուց հետո այն ունի հետևյալ տեսքը.

Magento 2. ներմուծել ապրանքներ անմիջապես տվյալների բազա

Категории

Հիմնական աղյուսակներ, որոնք պարունակում են տվյալներ ըստ կատեգորիաների.

  • catalog_category_entityկատեգորիաների ռեգիստր;
  • catalog_category_productկապ ապրանքների և կատեգորիաների միջև.
  • catalog_category_entity_*EAV հատկանիշի արժեքները;

Սկզբում, դատարկ Magento հավելվածում, կատեգորիաների ռեեստրը պարունակում է 2 կատեգորիա (ես կրճատել եմ սյունակների անունները. 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|

ID=1-ով կատեգորիան ամբողջ Magento կատալոգի արմատն է և հասանելի չէ ոչ ադմինիստրատորի վահանակում, ոչ էլ առաջին էջում: Կատեգորիա id=2-ով (Կանխադրված կատեգորիա) հիմնական կայքի հիմնական խանութի արմատային կատեգորիան է (Հիմնական կայք խանութ) ստեղծվել է, երբ հավելվածը տեղակայվում է (տես. Ադմինիստրատոր / Խանութներ / Բոլոր խանութները) Ավելին, խանութի արմատային կատեգորիան ինքնին նույնպես հասանելի չէ առջևում, միայն դրա ենթակատեգորիաները:

Քանի որ այս հոդվածի թեման դեռևս ապրանքների վերաբերյալ տվյալների ներմուծումն է, ես կատեգորիաներ ստեղծելիս չեմ օգտագործի տվյալների բազայի ուղղակի մուտքը, այլ կօգտագործեմ հենց Magento-ի կողմից տրամադրված դասերը (մոդելներ և պահեստներ): Տվյալների բազայի ուղղակի մուտքն օգտագործվում է միայն ներմուծված ապրանքը կատեգորիայի հետ կապելու համար (կատեգորիան համընկնում է իր անվան հետ, իսկ կատեգորիայի 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);
}

«Կատեգորիա 1» և «Կատեգորիա 2» կատեգորիաներին ապրանքի հղում ավելացնելուց հետո ադմինիստրատորի վահանակում ապրանքի մանրամասները նման են հետևյալին.

Magento 2. ներմուծել ապրանքներ անմիջապես տվյալների բազա

Լրացուցիչ գործողություններ

Տվյալների ներմուծումն ավարտվելուց հետո դուք պետք է կատարեք հետևյալ լրացուցիչ քայլերը.

  • տվյալների ինդեքսավորում. զանգահարեք վահանակում ./bin/magento indexer:reindex;
  • ապրանքների/կատեգորիաների URL-ների վերականգնում. կարող եք օգտագործել ընդլայնումը «elgentos/regenerate-catalog-urls«

Ապրանքներ ադմինիստրատորի վահանակում լրացուցիչ գործողություններ կատարելուց հետո.

Magento 2. ներմուծել ապրանքներ անմիջապես տվյալների բազա

և առջևում:

Magento 2. ներմուծել ապրանքներ անմիջապես տվյալների բազա

Ամփոփում

Ապրանքների նույն հավաքածուն (10 հատ), ինչպես նախորդ հոդվածում, ներմուծվում է առնվազն մեծության կարգով ավելի արագ (1 վայրկյան ընդդեմ 10-ի): Արագությունը ավելի ճշգրիտ գնահատելու համար ձեզ հարկավոր է ավելի մեծ քանակությամբ ապրանքներ՝ մի քանի հարյուր, կամ ավելի լավ՝ հազարավոր: Այնուամենայնիվ, նույնիսկ մուտքային տվյալների նման փոքր չափի դեպքում մենք կարող ենք եզրակացնել, որ Magento-ի կողմից տրամադրված գործիքների օգտագործումը (մոդելներ և պահոցներ) նշանակալի է (ընդգծում եմ. շատ!) արագացնել անհրաժեշտ ֆունկցիոնալության զարգացումը, բայց միևնույն ժամանակ զգալիորեն (ընդգծում եմ. շատ!) նվազեցնել տվյալների բազան մուտքագրելու արագությունը:

Արդյունքում ջուրը թաց է ստացվել, և սա բացահայտում չէ։ Այնուամենայնիվ, այժմ ես ունեմ այն ​​կոդը, որի հետ պետք է խաղալ և գուցե ավելի հետաքրքիր եզրակացությունների հանգեմ:

Source: www.habr.com