Magento 2: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

В oldingi maqola Men Magento 2-ga mahsulotlarni import qilish jarayonini odatiy usulda - modellar va omborlar orqali tasvirlab berdim. Odatiy usul juda past ma'lumotlarni qayta ishlash tezligiga ega. Mening noutbukim soniyada taxminan bitta mahsulot ishlab chiqarardi. Ushbu davomda men mahsulotni import qilishning muqobil usulini ko'rib chiqaman - standart Magento 2 mexanizmlarini (modellar, fabrikalar, omborlar) chetlab o'tib, ma'lumotlar bazasiga to'g'ridan-to'g'ri kirish orqali. Mahsulotlarni import qilish bosqichlari ketma-ketligi MySQL bilan ishlay oladigan har qanday dasturlash tiliga moslashtirilishi mumkin.

Masʼuliyatdan voz kechish: Magento uchun tayyor funksiya mavjud ma'lumotlarni import qilish va, ehtimol, bu siz uchun etarli bo'ladi. Biroq, agar sizda mavjud bo'lgan narsalar uchun CSV faylini tayyorlash bilan cheklanib qolmasdan, import jarayoni ustidan to'liqroq nazorat kerak bo'lsa, mushukka xush kelibsiz.

Magento 2: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

Ikkala maqolani yozish natijasida paydo bo'lgan kodni Magento modulida ko'rish mumkin "flancer32/mage2_ext_demo_import". Demo modul kodini soddalashtirish uchun men amal qilgan ba'zi cheklovlar:

  • Mahsulotlar faqat yaratiladi, yangilanmaydi.
  • Bitta ombor
  • Faqat turkum nomlari ularning tuzilishisiz import qilinadi
  • Ma'lumotlar tuzilmalari 2.3 versiyasiga mos keladi

Bitta mahsulotni import qilish uchun 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"
}

Importning asosiy bosqichlariga umumiy nuqtai

  • mahsulotning o'zini ro'yxatdan o'tkazish
  • mahsulot va veb-sayt o'rtasidagi aloqa
  • asosiy mahsulot atributlari (EAV)
  • inventarizatsiya ma'lumotlari (stokdagi mahsulot miqdori)
  • ommaviy axborot vositalari (rasmlar)
  • katalog toifalari bilan bog'lanish

Mahsulotni ro'yxatdan o'tkazish

Mahsulot haqida asosiy ma'lumotni quyidagi sahifada topishingiz mumkin 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`)
)

Mahsulot reestriga yozuv yaratish uchun zarur bo'lgan minimal ma'lumotlar:

  • attribute_set_id
  • sku

qo'shimcha:

  • type_id — agar biz buni aniqlamasak, u holda "oddiy" ishlatiladi

To'g'ridan-to'g'ri ma'lumotlar bazasiga yozish uchun men Magento-ning ma'lumotlar bazasi adapteridan foydalanaman:

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

Mahsulotni ro'yxatdan o'tkazgandan so'ng catalog_product_entity u administrator panelida, mahsulot tarmog'ida ko'rinadi (Katalog/mahsulotlar).

Magento 2: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

Mahsulot va veb-sayt o'rtasidagi aloqa

Mahsulotning sayt bilan assotsiatsiyasi mahsulotning qaysi do'konlarda va ko'rgazmalarda old tomonida bo'lishini aniqlaydi.

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: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

Mahsulotning asosiy atributlari

Yangi ro'yxatdan o'tgan mahsulot hali nomi yoki tavsifiga ega emas. Bularning barchasi orqali amalga oshiriladi EAV atributlari. Bu erda mahsulotning old tomonida to'g'ri ko'rsatilishi uchun zarur bo'lgan asosiy mahsulot atributlari ro'yxati keltirilgan:

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

Bunday mahsulotga alohida atribut qo'shiladi (uning kodidan atributning identifikatori va turini olish tafsilotlari o'tkazib yuborilgan):

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

Atribut kodidan foydalanib, biz uning identifikatori va ma'lumotlar turini aniqlaymiz (datetime, decimal, int, text, varchar), keyin ma'muriy oyna uchun ma'lumotlarni tegishli jadvalga yozing (store_id = 0).

Mahsulotga yuqoridagi atributlarni qo'shgandan so'ng, administrator panelida ushbu rasmni olasiz:

Magento 2: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

Inventarizatsiya ma'lumotlari

Magento-ning 2.3 versiyasidan boshlab, inventar ma'lumotlarini (mahsulot miqdori) saqlashni ta'minlaydigan ikkita parallel jadvallar to'plami mavjud:

  • cataloginventory_*: eski tuzilish;
  • inventory_*: yangi tuzilma (MSI - Multi Source Inventory);

Har ikkala tuzilmaga inventarizatsiya ma'lumotlarini qo'shishingiz kerak, chunki yangi tuzilma hali eskisidan to'liq mustaqil emas (ehtimol default yangi tuzilmada ombor stol ishtirok etadi cataloginventory_stock_status sifatda inventory_stock_1).

katalogi_

Magneto 2.3 ni o'rnatishda bizda dastlab 2 ta yozuv mavjud store_website, bu ikkita saytga mos keladi - ma'muriy va asosiy mijoz:

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

Jadval cataloginventory_stock bizda faqat bitta kirish mavjud:

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

Ya'ni bizning eski tuzilmamizda faqat bitta "ombor" mavjud (stock) va u ma'muriy veb-saytga bog'langan. Administrator paneli orqali yangilarini qo'shish sources/stocks MSI da (yangi tuzilma) yangi yozuvlarni keltirib chiqarmaydi cataloginventory_stock.

Eski tuzilmadagi mahsulotlar to'g'risidagi inventarizatsiya ma'lumotlari dastlab jadvallarda qayd etiladi:

  • cataloginventory_stock_item
  • cataloginventory_stock_status

katalog_inventar_zaxira_elementi

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

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

inventar_

Dastlab, inventarizatsiya ma'lumotlarini saqlash uchun yangi tuzilmada 1 "manba"(inventory_source):

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

va bitta "omborxona"(inventory_stock):

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

«manba» mahsulotlar uchun jismoniy xotirani ifodalaydi (yozuvda jismoniy koordinatalar va pochta manzili mavjud). "Sklad"bir nechta "manbalar" ning mantiqiy birlashmasi (inventory_source_stock_link)

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

savdo kanaliga ulanish sodir bo'lgan darajada (inventory_stock_sales_channel)

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

Ma'lumotlar tuzilishiga ko'ra, har xil turdagi savdo kanallari taxmin qilinadi, ammo sukut bo'yicha faqat ulanish "aksiyadorlik"-"Veb-sayt"(veb-saytga havola veb-sayt kodiga amal qiladi - base).

bitta"omborxona"bir nechta bilan bog'lanishi mumkin"manbalar"va bitta"manba"- bir nechta"omborlar"(ko'pdan ko'pga munosabatlar). Istisnolar sukut bo'yicha "manba"Va"omborxona". Ular boshqa ob'ektlar bilan qayta bog'lanmagan (kod darajasida cheklash - xato "Standart manba yoki birlamchi fond bilan bog‘liq havolani saqlab bo‘lmaydi"). Magento 2-dagi MSI tuzilishi haqida batafsil ma'lumotni maqolada topishingiz mumkin.CQRS va Event Sourcing yordamida omborlarni boshqarish tizimi. Dizayn".

Men standart konfiguratsiyadan foydalanaman va barcha inventar ma'lumotlarini manbaga qo'shaman default, kod bilan veb-sayt bilan bog'langan savdo kanalida ishtirok etadigan base (do'konning old tomoniga to'g'ri keladi - qarang 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);
}

Administrator panelidagi mahsulotga inventar ma'lumotlarini qo'shgandan so'ng, siz quyidagi rasmni olasiz:

Magento 2: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

axborot vositalari

Administrator paneli orqali mahsulotga rasmni "qo'lda" qo'shganda, tegishli ma'lumotlar quyidagi jadvallarda yoziladi:

  • catalog_product_entity_media_gallery: media reestri (tasvirlar va video fayllar);
  • catalog_product_entity_media_gallery_value: ommaviy axborot vositalarini mahsulotlar va vitrinalar bilan bog'lash (mahalliylashtirish);
  • catalog_product_entity_media_gallery_value_to_entity: mediani faqat mahsulotlarga ulash (ehtimol, mahsulot uchun standart media kontenti);
  • catalog_product_entity_varchar: Bu yerda tasvir ishlatiladigan rollar saqlanadi;

va rasmlarning o'zi katalogga saqlanadi ./pub/media/catalog/product/x/y/qayerda x и y — rasm fayli nomining birinchi va ikkinchi harflari. Masalan, fayl image.png sifatida saqlanishi kerak ./pub/media/catalog/product/i/m/image.png, shuning uchun platforma katalogdagi mahsulotlarni tavsiflashda tasvir sifatida foydalanishi mumkin.

Ro'yxatdan o'tish joyi e'lon qilingan ./pub/media/catalog/product/ media fayli (faylni joylashtirish jarayoni ushbu maqolada muhokama qilinmaydi):

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

Ro'yxatdan o'tganda, yangi media faylga identifikator beriladi.

Biz roʻyxatdan oʻtgan media faylni standart vitrina uchun mos mahsulot bilan bogʻlaymiz:

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

Biz ro'yxatdan o'tgan media faylni hech qanday do'konga bog'lanmasdan mos mahsulot bilan bog'laymiz. Bu ma'lumotlarning aynan qayerda qo'llanilishi va nima uchun oldingi jadvaldagi ma'lumotlarga kirish imkoni yo'qligi aniq emas, lekin bu jadval mavjud va mahsulotga rasm qo'shilganda ma'lumotlar unga yoziladi. Shunday ekan.

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

katalog_mahsulot_obyekt_varchar

Media fayl turli rollarda ishlatilishi mumkin (tegishli atribut kodi qavs ichida ko'rsatilgan):

  • Baza(image)
  • Kichik rasm (small_image)
  • Eskiz (thumbnail)
  • Tasvir namunasi (swatch_image)

Rollarni media faylga ulash aynan nima sodir bo'ladi catalog_product_entity_varchar. Bog'lanish kodi ""dagi kodga o'xshaydi.Mahsulotning asosiy atributlari".

Administrator panelidagi mahsulotga rasm qo'shgandan so'ng u quyidagicha ko'rinadi:

Magento 2: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

kategoriya

Kategoriya bo'yicha ma'lumotlarni o'z ichiga olgan asosiy jadvallar:

  • catalog_category_entity: toifalar reestri;
  • catalog_category_product: mahsulotlar va toifalar o'rtasidagi aloqa;
  • catalog_category_entity_*: EAV atribut qiymatlari;

Dastlab, bo'sh Magento ilovasida toifalar reestrida 2 toifa mavjud (ustun nomlarini qisqartirdim: 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 boʻlgan turkum butun Magento katalogining ildizidir va u administrator panelida ham, bosh sahifada ham mavjud emas. id=2 boʻlgan turkum (Birlamchi toifa) asosiy saytning asosiy doʻkonining ildiz toifasi (Asosiy veb-sayt do'koni) ilova o'rnatilganda yaratilgan (qarang. Administrator / Do'konlar / Barcha do'konlar). Bundan tashqari, do'konning asosiy toifasi ham old tomonda mavjud emas, faqat uning pastki toifalari.

Ushbu maqolaning mavzusi hali ham mahsulotlar to'g'risidagi ma'lumotlarni import qilish bo'lganligi sababli, men toifalarni yaratishda ma'lumotlar bazasiga to'g'ridan-to'g'ri kirishdan foydalanmayman, balki Magento tomonidan taqdim etilgan sinflardan (modellar va omborlar) foydalanaman. Ma'lumotlar bazasiga to'g'ridan-to'g'ri kirish faqat import qilingan mahsulotni toifa bilan bog'lash uchun ishlatiladi (toifa uning nomi bilan mos keladi va toifa identifikatori moslashtirish vaqtida olinadi):

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-toifa" va "2-toifa" toifalariga mahsulot havolasini qo'shgandan so'ng, administrator panelidagi mahsulot tafsilotlari quyidagicha ko'rinadi:

Magento 2: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

Qo'shimcha harakatlar

Ma'lumotlarni import qilish tugallangach, quyidagi qo'shimcha amallarni bajarishingiz kerak:

  • ma'lumotlarni indekslash: konsolda qo'ng'iroq qiling ./bin/magento indexer:reindex;
  • Mahsulotlar/toifalar uchun URL manzillarini qayta tiklash: kengaytmadan foydalanishingiz mumkinelgentos/regenerate-catalog-urls«

Qo'shimcha amallarni bajargandan so'ng, administrator panelidagi mahsulotlar:

Magento 2: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

va old tomondan:

Magento 2: mahsulotlarni to'g'ridan-to'g'ri ma'lumotlar bazasiga import qiling

Xulosa

Avvalgi maqolada bo'lgani kabi bir xil mahsulotlar to'plami (10 dona) hech bo'lmaganda kattalikdagi tezroq import qilinadi (1 ga nisbatan 10 soniya). Tezlikni aniqroq baholash uchun sizga ko'proq miqdordagi mahsulotlar kerak bo'ladi - bir necha yuz yoki undan ham yaxshiroq minglab. Biroq, kirish ma'lumotlarining bunday kichik hajmiga qaramay, biz Magento tomonidan taqdim etilgan vositalardan (modellar va omborlar) foydalanish muhim degan xulosaga kelishimiz mumkin (ta'kidlayman - ko'p!) kerakli funksionallikni rivojlantirishni tezlashtirish, lekin shu bilan birga sezilarli darajada (ta'kidlayman - ko'p!) ma'lumotlarning ma'lumotlar bazasiga kirish tezligini pasaytiring.

Natijada, suv ho'l bo'lib chiqdi va bu vahiy emas. Biroq, endi menda o'ynash uchun kod bor va ehtimol yana qiziqarli xulosalarga kelaman.

Manba: www.habr.com