Magento 2: məhsulların birbaşa verilənlər bazasına idxalı

В əvvəlki məqalə Mən Magento 2-yə məhsulların idxalı prosesini adi şəkildə - modellər və depolar vasitəsilə təsvir etdim. Adi metod çox aşağı məlumat emal sürətinə malikdir. Laptopum saniyədə təxminən bir məhsul istehsal edirdi. Bu davamda mən bir məhsulu idxal etməyin alternativ yolunu nəzərdən keçirirəm - standart Magento 2 mexanizmlərini (modellər, fabriklər, depolar) keçərək verilənlər bazasına birbaşa daxil olmaq. Məhsulların idxalı üçün addımların ardıcıllığı MySQL ilə işləyə bilən istənilən proqramlaşdırma dilinə uyğunlaşdırıla bilər.

Məsuliyyətdən imtina: Magento üçün hazır funksionallıq var məlumat idxalı və çox güman ki, sizin üçün kifayət edəcək. Bununla belə, idxal prosesi üzərində daha tam nəzarətə ehtiyacınız varsa, əlinizdə olanlar üçün CSV faylı hazırlamaqla məhdudlaşmırsa, cat-a xoş gəlmisiniz.

Magento 2: məhsulların birbaşa verilənlər bazasına idxalı

Hər iki məqalənin yazılması nəticəsində yaranan kod Magento modulunda görünə bilər "flancer32/mage2_ext_demo_import". Demo modul kodunu sadələşdirmək üçün izlədiyim bəzi məhdudiyyətlər bunlardır:

  • Məhsullar yalnız yaradılmışdır, yenilənmir.
  • Bir anbar
  • Yalnız kateqoriya adları strukturu olmadan idxal olunur
  • Məlumat strukturları 2.3 versiyasına uyğundur

Tək məhsulun idxalı üçün 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"
}

İdxalın əsas mərhələlərinə ümumi baxış

  • məhsulun özünün qeydiyyatı
  • məhsul və veb sayt arasında əlaqə
  • əsas məhsul atributları (EAV)
  • inventar məlumatları (anbarda olan məhsulun miqdarı)
  • media (şəkillər)
  • kataloq kateqoriyaları ilə əlaqə

Məhsulun qeydiyyatı

Əsas məhsul haqqında məlumatı burada tapa bilərsiniz 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`)
)

Məhsul reyestrində qeyd yaratmaq üçün tələb olunan minimum məlumat:

  • attribute_set_id
  • sku

əlavə:

  • type_id — onu qeyd etməsək, onda 'sadə' istifadə olunacaq

Birbaşa verilənlər bazasına yazmaq üçün mən Magento-nun özünün DB adapterindən istifadə edirəm:

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

ilə məhsulu qeydiyyatdan keçirdikdən sonra catalog_product_entity admin panelində, məhsul şəbəkəsində görünən olur (Kataloq/Məhsullar).

Magento 2: məhsulların birbaşa verilənlər bazasına idxalı

Məhsul və veb sayt arasında əlaqə

Məhsulun saytla assosiasiyası məhsulun ön tərəfdə hansı mağazalarda və vitrinlərdə olacağını müəyyən edir.

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: məhsulların birbaşa verilənlər bazasına idxalı

Əsas məhsul atributları

Yeni qeydiyyatdan keçmiş məhsulun hələ adı və təsviri yoxdur. Bütün bunlar vasitəsilə həyata keçirilir EAV atributları. Budur, məhsulun ön tərəfdə düzgün şəkildə göstərilməsi üçün lazım olan əsas məhsul atributlarının siyahısı:

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

Bu kimi bir məhsula ayrıca atribut əlavə olunur (onun kodundan atributun identifikatorunun və tipinin alınması təfərrüatları buraxılıb):

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 kodundan istifadə edərək onun id və məlumat növünü müəyyən edirik (datetime, decimal, int, text, varchar), sonra inzibati pəncərə üçün məlumatları müvafiq cədvələ yazın (store_id = 0).

Yuxarıdakı atributları məhsula əlavə etdikdən sonra admin panelində bu şəkli əldə edirsiniz:

Magento 2: məhsulların birbaşa verilənlər bazasına idxalı

İnventar məlumatları

Magento-da 2.3 versiyasından başlayaraq, inventar məlumatının (məhsulun miqdarı) saxlanmasını təmin edən iki paralel cədvəl dəsti mövcuddur:

  • cataloginventory_*: köhnə quruluş;
  • inventory_*: yeni struktur (MSI - Multi Source Inventory);

Hər iki struktura inventar məlumatları əlavə etməlisiniz, çünki yeni struktur hələ köhnə strukturdan tam müstəqil deyil (çox güman ki, üçün default Yeni quruluşda anbarda bir masa iştirak edir cataloginventory_stock_status kimi inventory_stock_1).

kataloq inventar_

Magneto 2.3 tətbiq edərkən əvvəlcə 2 girişimiz var store_website, iki sayta uyğundur - inzibati və əsas müştəri:

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

Cədvəl cataloginventory_stock yalnız bir girişimiz var:

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

Yəni köhnə quruluşumuzda yalnız bir “anbar” var (stock) və o, inzibati veb-saytla əlaqələndirilir. İdarəetmə paneli vasitəsilə yenilərinin əlavə edilməsi sources/stocks MSI-də (yeni struktur) yeni girişlərlə nəticələnmir cataloginventory_stock.

Köhnə strukturda olan məhsullar haqqında inventar məlumatları əvvəlcə cədvəllərdə qeyd olunur:

  • cataloginventory_stock_item
  • cataloginventory_stock_status

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

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

inventar_

Əvvəlcə inventar məlumatlarının saxlanması üçün yeni strukturda 1 "mənbə(inventory_source):

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

və bir "anbar(inventory_stock):

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

«Mənbə» məhsulların fiziki yaddaşını təmsil edir (qeyddə fiziki koordinatlar və poçt ünvanı var). "Anbar"bir neçə "mənbənin" məntiqi birliyidir (inventory_source_stock_link)

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

satış kanalına qoşulmanın baş verdiyi səviyyədə (inventory_stock_sales_channel)

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

Məlumat strukturuna əsasən, müxtəlif növ satış kanalları nəzərdə tutulur, lakin standart olaraq yalnız əlaqə "səhmdar"-"veb"(saytın linki vebsayt koduna uyğundur - base).

bir"anbar"bir neçə ilə əlaqələndirilə bilər"mənbələrə"və bir"mənbə"- bir neçəyə"anbarlar"(çoxdan çoxa əlaqə). İstisnalar standartdır"mənbə"Və"anbar". Onlar digər qurumlarla yenidən əlaqələndirilmir (kod səviyyəsində məhdudiyyət - xəta "Defolt Mənbə və ya Defolt Səhm ilə əlaqəli linki saxlamaq mümkün deyil"). Magento 2-də MSI strukturu haqqında daha ətraflı məlumatı məqalədə tapa bilərsiniz.CQRS və Event Sourcing istifadə edərək anbar idarəetmə sistemi. Dizayn".

Mən standart konfiqurasiyadan istifadə edəcəyəm və bütün inventar məlumatlarını mənbəyə əlavə edəcəyəm default, kodu ilə veb saytla əlaqəli satış kanalında iştirak edən base (mağazanın ön hissəsinə uyğundur - baxın 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);
}

İdarə panelində məhsula inventar məlumatı əlavə etdikdən sonra bu şəkli əldə edirsiniz:

Magento 2: məhsulların birbaşa verilənlər bazasına idxalı

Media

İdarəetmə paneli vasitəsilə məhsula şəkil “əl ilə” əlavə edildikdə, müvafiq məlumatlar aşağıdakı cədvəllərdə yazılır:

  • catalog_product_entity_media_gallery: media reyestri (şəkillər və video faylları);
  • catalog_product_entity_media_gallery_value: medianın məhsul və vitrinlərlə əlaqələndirilməsi (lokallaşdırma);
  • catalog_product_entity_media_gallery_value_to_entity: medianın yalnız məhsullarla əlaqələndirilməsi (ehtimal ki, məhsul üçün standart media məzmunu);
  • catalog_product_entity_varchar: Təsvirin istifadə olunduğu rollar burada saxlanılır;

və şəkillərin özləri kataloqda saxlanılır ./pub/media/catalog/product/x/y/Hara x и y — şəkil faylının adının birinci və ikinci hərfləri. Məsələn, fayl image.png kimi saxlanmalıdır ./pub/media/catalog/product/i/m/image.png, belə ki, platforma kataloqdan məhsulları təsvir edərkən ondan şəkil kimi istifadə edə bilsin.

Qeydiyyat yerləşdirilib ./pub/media/catalog/product/ media faylı (faylın özünü yerləşdirmə prosesi bu məqalədə müzakirə edilmir):

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

Qeydiyyatdan keçdikdə yeni media faylına identifikator təyin edilir.

Biz qeydiyyatdan keçmiş media faylını standart vitrin üçün uyğun məhsulla əlaqələndiririk:

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 qeydiyyatdan keçmiş media faylını heç bir vitrinlə bağlı olmadan müvafiq məhsulla əlaqələndiririk. Bu məlumatların dəqiq harada istifadə edildiyi və nə üçün əvvəlki cədvəldəki məlumatlara daxil olmaq mümkün olmadığı aydın deyil, lakin bu cədvəl mövcuddur və məhsula şəkil əlavə edildikdə məlumatlar ona yazılır. Beləliklə, bu qədər.

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

Media faylı müxtəlif rollarla istifadə edilə bilər (müvafiq atribut kodu mötərizədə göstərilir):

  • Baza(image)
  • Kiçik Şəkil (small_image)
  • Miniatür (thumbnail)
  • Şəkil nümunəsi (swatch_image)

Rolları bir media faylına bağlamaq tam olaraq baş verənlərdir catalog_product_entity_varchar. Bağlama kodu ""dakı koda bənzəyir.Əsas məhsul atributları".

Admin panelində məhsula şəkil əlavə etdikdən sonra belə görünür:

Magento 2: məhsulların birbaşa verilənlər bazasına idxalı

Kateqoriyalar

Kateqoriyaya görə məlumatları ehtiva edən əsas cədvəllər:

  • catalog_category_entity: kateqoriyaların reyestri;
  • catalog_category_product: məhsullar və kateqoriyalar arasında əlaqə;
  • catalog_category_entity_*: EAV atribut dəyərləri;

Əvvəlcə boş bir Magento tətbiqində kateqoriya reyestrində 2 kateqoriya var (sütun adlarını qısalddım: 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|

İd=1 olan kateqoriya bütün Magento kataloqunun köküdür və nə admin panelində, nə də ön səhifədə mövcud deyil. id=2 olan kateqoriya (Defolt Kateqoriya) əsas saytın əsas mağazası üçün kök kateqoriyadır (Əsas Vebsayt Mağazası) proqram yerləşdirildikdə yaradılmışdır (bax. Admin / Mağazalar / Bütün Mağazalar). Üstəlik, mağazanın özünün kök kateqoriyası da ön tərəfdə mövcud deyil, yalnız alt kateqoriyalarıdır.

Bu məqalənin mövzusu hələ də məhsullar haqqında məlumatların idxalı olduğundan, kateqoriyalar yaradarkən verilənlər bazasına birbaşa girişdən istifadə etməyəcəyəm, lakin Magento tərəfindən təqdim olunan siniflərdən (modellər və depolar) istifadə edəcəyəm. Verilənlər bazasına birbaşa giriş yalnız idxal olunan məhsulu kateqoriya ilə əlaqələndirmək üçün istifadə olunur (kateqoriya onun adı ilə uyğunlaşdırılır və uyğunluq zamanı kateqoriya id-si alınır):

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

"Kateqoriya 1" və "Kateqoriya 2" kateqoriyalarına məhsul linki əlavə etdikdən sonra admin panelində məhsul təfərrüatları belə görünür:

Magento 2: məhsulların birbaşa verilənlər bazasına idxalı

Əlavə tədbirlər

Məlumatların idxalı tamamlandıqdan sonra aşağıdakı əlavə addımları yerinə yetirməlisiniz:

  • məlumatların indeksləşdirilməsi: konsolda zəng edin ./bin/magento indexer:reindex;
  • məhsullar/kateqoriyalar üçün URL-lərin bərpası: “ uzantısından istifadə edə bilərsinizelgentos/regenerate-catalog-url«

Əlavə hərəkətləri yerinə yetirdikdən sonra admin panelindəki məhsullar:

Magento 2: məhsulların birbaşa verilənlər bazasına idxalı

və ön tərəfdə:

Magento 2: məhsulların birbaşa verilənlər bazasına idxalı

Xülasə

Əvvəlki məqalədə olduğu kimi eyni məhsul dəsti (10 ədəd) ən azı böyüklükdə daha sürətli idxal olunur (1-a qarşı 10 saniyə). Sürəti daha dəqiq qiymətləndirmək üçün daha çox sayda məhsula ehtiyacınız var - bir neçə yüz və ya daha yaxşısı minlərlə. Bununla belə, giriş məlumatlarının belə kiçik ölçüsü ilə belə nəticəyə gələ bilərik ki, Magento tərəfindən təmin edilən alətlərin (modellər və depolar) istifadəsi əhəmiyyətlidir (vurğulayıram - çox!) tələb olunan funksionallığın inkişafını sürətləndirin, lakin eyni zamanda əhəmiyyətli dərəcədə (vurğulayıram - çox!) verilənlərin verilənlər bazasına daxil olma sürətini azaltmaq.

Nəticədə suyun nəm olduğu ortaya çıxdı və bu vəhy deyil. Ancaq indi mənim oynamaq üçün kodum var və bəlkə də daha maraqlı nəticələrə gələ bilərəm.

Mənbə: www.habr.com