Magento 2: direkta nga pag-import sa mga produkto sa database

Π’ miaging artikulo Gihubit nako ang proseso sa pag-import sa mga produkto sa Magento 2 sa naandan nga paagi - pinaagi sa mga modelo ug mga repositoryo. Ang naandan nga pamaagi adunay gamay kaayo nga katulin sa pagproseso sa datos. Ang akong laptop naghimo og mga usa ka produkto matag segundo. Niini nga pagpadayon, akong gikonsiderar ang usa ka alternatibong paagi sa pag-import sa usa ka produkto - pinaagi sa direkta nga pagsulod sa database, pag-bypass sa standard nga mekanismo sa Magento 2 (mga modelo, pabrika, mga repositoryo). Ang han-ay sa mga lakang sa pag-import sa mga produkto mahimong ipahiangay sa bisan unsang programming language nga magamit sa MySQL.

Disclaimer: Ang Magento adunay andam na nga gamit para sa import sa datos ug, lagmit, igo na kini kanimo. Bisan pa, kung kinahanglan nimo ang labi ka kompleto nga pagkontrol sa proseso sa pag-import, dili limitado sa pag-andam sa usa ka CSV file alang sa kung unsa ang naa kanimo, welcome sa iring.

Magento 2: direkta nga pag-import sa mga produkto sa database

Ang kodigo nga resulta sa pagsulat sa duha ka artikulo mahimong makita sa Magento module "flancer32/mage2_ext_demo_import". Ania ang pipila ka mga pagdili nga akong gisunod aron pasimplehon ang demo module code:

  • Ang mga produkto gimugna lamang, wala gi-update.
  • Usa ka bodega
  • Ang mga ngalan sa kategorya lamang ang gi-import, nga wala ang ilang istruktura
  • Ang mga istruktura sa datos nagsunod sa bersyon 2.3

JSON alang sa pag-import sa usa ka produkto:

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

Overview sa mga nag-unang yugto sa import

  • pagrehistro sa produkto mismo
  • koneksyon tali sa produkto ug website
  • batakang mga hiyas sa produkto (EAV)
  • data sa imbentaryo (kadaghanon sa produkto sa stock)
  • media (mga hulagway)
  • koneksyon sa mga kategorya sa katalogo

Pagparehistro sa Produkto

Panguna nga impormasyon sa produkto makita sa 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`)
)

Ang minimum nga impormasyon nga gikinahanglan sa paghimo og entry sa rehistro sa produkto mao ang:

  • attribute_set_id
  • sku

dugang:

  • type_id β€” kung dili nato kini i-specify, unya 'simple' ang gamiton

Sa pagsulat direkta sa database, akong gigamit ang DB adapter sa Magento mismo:

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

Human marehistro ang produkto sa catalog_product_entity makita kini sa admin panel, sa grid sa produkto (Katalogo/Mga Produkto).

Magento 2: direkta nga pag-import sa mga produkto sa database

Relasyon tali sa produkto ug website

Ang asosasyon sa produkto sa site nagtino kung asa nga mga tindahan ug gipakita ang produkto nga magamit sa atubangan.

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: direkta nga pag-import sa mga produkto sa database

Panguna nga mga kinaiya sa produkto

Ang bag-ong narehistro nga produkto wala pa'y ngalan o deskripsyon. Kining tanan gihimo pinaagi sa Mga hiyas sa EAV. Ania ang usa ka lista sa sukaranan nga mga hiyas sa produkto nga gikinahanglan aron ang produkto mapakita sa husto sa atubangan:

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

Ang usa ka lahi nga hiyas gidugang sa usa ka produkto nga sama niini (ang mga detalye sa pagkuha sa identifier ug tipo sa hiyas gikan sa code niini wala iapil):

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

Gamit ang attribute code, atong matino ang id ug data type niini (datetime, decimal, int, text, varchar), unya isulat ang datos alang sa administratibong bintana sa angay nga lamesa (store_id = 0).

Pagkahuman idugang ang mga hiyas sa ibabaw sa produkto, makuha nimo kini nga litrato sa admin panel:

Magento 2: direkta nga pag-import sa mga produkto sa database

Data sa imbentaryo

Sugod sa bersyon 2.3 sa Magento, adunay duha ka managsama nga set sa mga lamesa nga naghatag pagtipig sa impormasyon sa imbentaryo (gidaghanon sa produkto):

  • cataloginventory_*: daan nga istruktura;
  • inventory_*: bag-ong istruktura (MSI - Multi Source Inventory);

Kinahanglan nimong idugang ang datos sa imbentaryo sa duha nga istruktura, tungod kay ang bag-ong estraktura dili pa hingpit nga independente sa daan (malagmit nga alang sa default bodega sa bag-ong istruktura usa ka lamesa ang nalangkit cataloginventory_stock_status ingon nga inventory_stock_1).

cataloginventory_

Kung ang pag-deploy sa Magneto 2.3 sa una adunay 2 ka mga entry store_website, nga katumbas sa duha ka mga site - administratibo ug panguna nga kliyente:

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

Lamesa cataloginventory_stock naa ra tay entry:

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

Sa ato pa, sa atong karaang estraktura adunay usa ra ka "bodega" (stock) ug kini nalambigit sa administratibong website. Pagdugang mga bag-o pinaagi sa admin panel sources/stocks sa MSI (bag-ong istruktura) dili moresulta sa mga bag-ong entries sa cataloginventory_stock.

Ang datos sa imbentaryo bahin sa mga produkto sa daan nga istruktura una nga natala sa mga lamesa:

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

imbentaryo_

Sa sinugdan, ang bag-ong istruktura alang sa pagtipig sa datos sa imbentaryo naglangkob sa 1 "tinubdan"(inventory_source):

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

ug usa "bodega"(inventory_stock):

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

Β«TinubdanΒ» nagrepresentar sa pisikal nga pagtipig alang sa mga produkto (ang rekord adunay mga pisikal nga koordinasyon ug adres sa pagpadala). "Warehouse"usa ka lohikal nga panaghiusa sa daghang "mga tinubdan" (inventory_source_stock_link)

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

sa lebel diin mahitabo ang koneksyon sa sales channel (inventory_stock_sales_channel)

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

Sa paghukom sa istruktura sa datos, ang lainlaing mga lahi sa mga channel sa pagbaligya gituohan, apan pinaagi sa default ang koneksyon "stock"-"website"(ang link sa website nagsunod sa website code - base).

Sa usa ka "bodega"mahimong ma-link sa pipila"sa mga gigikanan"ug usa "tinubdan"- sa pipila"mga bodega"(many-to-many nga relasyon). Ang mga eksepsiyon kay default "tinubdan"Ug"bodega". Wala sila gi-link pag-usab sa ubang mga entidad (limitasyon sa lebel sa code - ang sayup "Dili ma-save ang link nga may kalabotan sa Default Source o Default Stock"). Ang dugang nga mga detalye bahin sa istruktura sa MSI sa Magento 2 makita sa artikulo nga "Sistema sa pagdumala sa bodega gamit ang CQRS ug Event Sourcing. Disenyo".

Akong gamiton ang default configuration ug idugang ang tanang impormasyon sa imbentaryo sa tinubdan default, nga nalangkit sa sales channel nga nalangkit sa website nga adunay code base (katugbang sa atubangan nga tumoy sa tindahan - tan-awa 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);
}

Pagkahuman sa pagdugang sa datos sa imbentaryo sa produkto sa admin panel, makuha nimo kini nga litrato:

Magento 2: direkta nga pag-import sa mga produkto sa database

Media

Kung "manual" nga nagdugang usa ka imahe sa usa ka produkto pinaagi sa admin panel, ang may kalabutan nga kasayuran gisulat sa mga mosunud nga lamesa:

  • catalog_product_entity_media_gallery: media registry (mga hulagway ug mga video file);
  • catalog_product_entity_media_gallery_value: pagsumpay sa media ngadto sa mga produkto ug mga showcase (lokalisasyon);
  • catalog_product_entity_media_gallery_value_to_entity: pagsumpay sa media ngadto sa mga produkto lamang (tingali default media content alang sa produkto);
  • catalog_product_entity_varchar: Ang mga tahas diin gigamit ang imahe gitipigan dinhi;

ug ang mga imahe mismo gitipigan sa direktoryo ./pub/media/catalog/product/x/y/diin x ΠΈ y - ang una ug ikaduha nga mga letra sa ngalan sa file sa imahe. Pananglitan, file image.png kinahanglan maluwas ingon ./pub/media/catalog/product/i/m/image.png, aron magamit kini sa plataporma ingon usa ka imahe kung naghulagway sa mga produkto gikan sa katalogo.

Register nga gi-post sa ./pub/media/catalog/product/ media file (ang proseso sa pagbutang sa file mismo wala hisgoti niini nga artikulo):

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

Kung narehistro, usa ka bag-ong media file ang gihatagan usa ka identifier.

Among gi-associate ang rehistradong media file sa katugbang nga produkto alang sa default storefront:

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

Among i-associate ang rehistradong media file sa katugbang nga produkto nga walay ihigot sa bisan unsang storefront. Dili klaro kung diin eksakto kini nga datos gigamit ug ngano nga imposible nga ma-access ang datos gikan sa miaging lamesa, apan kini nga lamesa naglungtad ug ang datos gisulat niini kung ang usa ka litrato gidugang sa produkto. So mao to.

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

Ang usa ka media file mahimong gamiton uban ang lain-laing mga tahas (ang katugbang nga attribute code gipakita sa parentesis):

  • Base(image)
  • Gamay nga Hulagway (small_image)
  • Thumbnail (thumbnail)
  • Hulagway sa Swatch (swatch_image)

Ang pag-link sa mga tahas sa usa ka media file mao gyud ang mahitabo catalog_product_entity_varchar. Ang binding code susama sa code sa "Panguna nga mga kinaiya sa produkto".

Pagkahuman sa pagdugang usa ka imahe sa produkto sa admin panel kini ingon niini:

Magento 2: direkta nga pag-import sa mga produkto sa database

Mga kategoriya

Panguna nga mga lamesa nga adunay mga datos sa kategorya:

  • catalog_category_entity: rehistro sa mga kategoriya;
  • catalog_category_product: koneksyon tali sa mga produkto ug mga kategoriya;
  • catalog_category_entity_*: EAV nga mga hiyas sa hiyas;

Sa sinugdan, sa usa ka walay sulod nga aplikasyon sa Magento, ang rehistro sa kategorya adunay 2 nga mga kategorya (Gimubo nako ang mga ngalan sa kolum: 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|

Ang kategorya nga adunay id=1 mao ang gamut sa tibuuk nga katalogo sa Magento ug dili magamit sa admin panel o sa atubangang panid. Kategorya nga adunay id=2 (Default nga Kategorya) mao ang gamut nga kategoriya alang sa nag-unang tindahan sa nag-unang site (Panguna nga Tindahan sa Website) gihimo sa diha nga ang aplikasyon gi-deploy (tan-awa. Admin / Tindahan / Tanan nga Tindahan). Dugang pa, ang gamut nga kategorya sa tindahan mismo dili usab magamit sa unahan, ang mga subcategory lamang niini.

Tungod kay ang hilisgutan niini nga artikulo nag-import pa sa datos sa mga produkto, dili ako mogamit direkta nga pagsulod sa database kung maghimo mga kategorya, apan gamiton ang mga klase nga gihatag sa Magento mismo (mga modelo ug mga repositoryo). Ang direkta nga pagsulod sa database gigamit lamang aron i-associate ang imported nga produkto sa usa ka kategorya (ang kategorya gipares sa ngalan niini, ug ang kategorya id makuha sa panahon sa pagpares):

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

Pagkahuman sa pagdugang usa ka link sa produkto sa mga kategorya nga "Kategorya 1" ug "Kategorya 2", ang mga detalye sa produkto sa admin panel ingon niini:

Magento 2: direkta nga pag-import sa mga produkto sa database

Dugang nga Mga Lihok

Kung kompleto na ang pag-import sa datos, kinahanglan nimong kompletohon ang mosunod nga dugang nga mga lakang:

  • data indexing: tawag sa console ./bin/magento indexer:reindex;
  • pag-usab sa mga URL para sa mga produkto/kategorya: mahimo nimong gamiton ang extension nga β€œelgentos/regenerate-catalog-urlsΒ«

Mga produkto sa admin panel human sa paghimo og dugang nga mga aksyon:

Magento 2: direkta nga pag-import sa mga produkto sa database

ug sa atubangan:

Magento 2: direkta nga pag-import sa mga produkto sa database

Sumaryo

Ang parehas nga hugpong sa mga produkto (10 ka piraso) sama sa miaging artikulo gi-import sa labing menos usa ka han-ay sa magnitude nga mas paspas (1 segundo batok sa 10). Aron mas tukma nga mabanabana ang katulin, kinahanglan nimo ang daghang mga produkto - pila ka gatos, o labi pa ka libo. Bisan pa, bisan sa ingon ka gamay nga gidak-on sa data sa pag-input, makahinapos kita nga ang paggamit sa mga himan nga gihatag sa Magento (mga modelo ug mga repositoryo) hinungdanon (akong gipasiugda - kamahinungdanon!) pagpadali sa pag-uswag sa gikinahanglan nga pagpaandar, apan sa samang higayon kamahinungdanon (akong gipasiugda - kamahinungdanon!) pakunhuran ang katulin sa pagsulod sa datos sa database.

Tungod niini, ang tubig nahimong basa ug dili kini usa ka pagpadayag. Bisan pa, karon ako adunay code nga dulaon ug tingali moabut sa pipila nga mas makapaikag nga mga konklusyon.

Source: www.habr.com