Magento 2: ngimpor produk langsung menyang database

Π’ artikel sadurunge Aku nerangake proses ngimpor produk menyang Magento 2 kanthi cara biasa - liwat model lan repositori. Cara biasanipun nduweni kacepetan pangolahan data sing sithik banget. Laptopku ngasilake kira-kira siji produk saben detik. Ing tutugan iki, aku nimbang cara alternatif kanggo ngimpor produk - kanthi entri langsung menyang database, ngliwati mekanisme standar Magento 2 (model, pabrik, repositori). Urutan langkah kanggo ngimpor produk bisa dicocogake karo basa pamrograman apa wae sing bisa digunakake karo MySQL.

Nolak tanggung jawab: Magento wis siap-digawe fungsi kanggo ngimpor data lan, paling kamungkinan, iku bakal cukup kanggo sampeyan. Nanging, yen sampeyan butuh kontrol sing luwih lengkap babagan proses impor, ora diwatesi kanggo nyiapake file CSV kanggo apa sing sampeyan duwe, welcome to cat.

Magento 2: ngimpor produk langsung menyang database

Kode asil saka nulis loro artikel bisa dideleng ing modul Magento "flancer32/mage2_ext_demo_import". Ing ngisor iki sawetara watesan sing daktindakake kanggo nyederhanakake kode modul demo:

  • Produk mung digawe, ora dianyari.
  • Gudang siji
  • Mung jeneng kategori sing diimpor, tanpa strukture
  • Struktur data tundhuk karo versi 2.3

JSON kanggo ngimpor produk siji:

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

Ringkesan tahapan utama impor

  • registrasi produk kasebut dhewe
  • sambungan antarane produk lan situs web
  • atribut produk dasar (EAV)
  • data persediaan (jumlah produk ing saham)
  • media (gambar)
  • sambungan karo kategori katalog

Registrasi produk

Informasi produk dhasar bisa ditemokake ing 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`)
)

Informasi minimal sing dibutuhake kanggo nggawe entri ing registri produk yaiku:

  • attribute_set_id
  • sku

tambahan:

  • type_id - yen kita ora nemtokake, banjur 'prasaja' bakal digunakake

Kanggo nulis langsung menyang database, aku nggunakake adaptor DB saka Magento dhewe:

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

Sawise ndhaptar produk karo catalog_product_entity katon ing panel admin, ing kothak produk (Katalog/Produk).

Magento 2: ngimpor produk langsung menyang database

Hubungan antarane produk lan situs web

Asosiasi produk karo situs kasebut nemtokake manawa nyimpen lan nampilake produk bakal kasedhiya ing ngarep.

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: ngimpor produk langsung menyang database

Atribut produk dhasar

Produk sing mentas kadhaptar durung duwe jeneng utawa katrangan. Kabeh iki rampung liwat atribut EAV. Mangkene dhaptar atribut produk dhasar sing dibutuhake supaya produk ditampilake kanthi bener ing ngarep:

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

Atribut kapisah ditambahake menyang produk kaya iki (rincian kanggo entuk pengenal lan jinis atribut saka kode kasebut diilangi):

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

Nggunakake kode atribut, kita nemtokake id lan jinis data (datetime, decimal, int, text, varchar), banjur tulis data kanggo jendhela administratif menyang tabel sing cocog (store_id = 0).

Sawise nambahake atribut ing ndhuwur menyang produk, sampeyan entuk gambar iki ing panel admin:

Magento 2: ngimpor produk langsung menyang database

Data persediaan

Miwiti saka versi 2.3 ing Magento, ana rong set tabel paralel sing nyedhiyakake panyimpenan informasi inventaris (jumlah produk):

  • cataloginventory_*: struktur lawas;
  • inventory_*: struktur anyar (MSI - Multi Source Inventory);

Sampeyan kudu nambah data persediaan kanggo loro struktur, amarga struktur anyar durung rampung independen saka lawas (iku banget kamungkinan sing kanggo default gudang ing struktur anyar Tabel melu cataloginventory_stock_status minangka inventory_stock_1).

katalog inventaris_

Nalika deploying Magneto 2.3 kita pisanan duwe 2 entri ing store_website, sing cocog karo rong situs - klien administratif lan utama:

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

Tabel cataloginventory_stock kita mung duwe siji entri:

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

Yaiku, ing struktur lawas kita mung ana siji "gudang" (stock) lan disambung menyang situs web administratif. Nambahake sing anyar liwat panel admin sources/stocks ing MSI (struktur anyar) ora ngasilake entri anyar ing cataloginventory_stock.

Data inventaris babagan produk ing struktur lawas wiwitane dicathet ing tabel:

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

inventaris_

Kaping pisanan, struktur anyar kanggo nyimpen data inventaris ngemot 1 "sumber"(inventory_source):

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

lan siji"gudang"(inventory_stock):

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

Β«SumberΒ» nggantosi panyimpenan fisik kanggo produk (cathetan ngemot koordinat fisik lan alamat layang). "Gudang"iku gabungan logis saka sawetara "sumber" (inventory_source_stock_link)

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

ing tingkat sing ana sambungan menyang saluran penjualan (inventory_stock_sales_channel)

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

Miturut struktur data, macem-macem jinis saluran penjualan dianggep, nanging kanthi standar mung sambungan "Simpenan"-"situs"(link menyang situs web ngetutake kode situs web - base).

siji"gudang"bisa nyambung menyang sawetara"sumber"lan siji"sumber"- kanggo sawetara"gudang"(hubungan many-to-many). Pengecualian minangka standar'sumber"Lan"gudang". Dheweke ora disambung maneh menyang entitas liyane (watesan ing tingkat kode - kesalahan "Ora bisa nyimpen link sing gegandhengan karo Sumber Default utawa Simpenan Default"). Rincian liyane babagan struktur MSI ing Magento 2 bisa ditemokake ing artikel "Sistem manajemen gudang nggunakake CQRS lan Event Sourcing. Desain".

Aku bakal nggunakake konfigurasi gawan lan nambah kabeh informasi persediaan kanggo sumber default, sing melu saluran penjualan sing ana gandhengane karo situs web kanthi kode kasebut base (cocog karo mburi ngarep toko - ndeleng 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);
}

Sawise nambahake data inventaris menyang produk ing panel admin, sampeyan entuk gambar iki:

Magento 2: ngimpor produk langsung menyang database

Media

Nalika "kanthi manual" nambahake gambar menyang produk liwat panel admin, informasi sing relevan ditulis ing tabel ing ngisor iki:

  • catalog_product_entity_media_gallery: pendaptaran media (gambar lan file video);
  • catalog_product_entity_media_gallery_value: ngubungake media menyang produk lan pameran (lokalisasi);
  • catalog_product_entity_media_gallery_value_to_entity: mung ngubungake media menyang produk (bisa uga konten media standar kanggo produk kasebut);
  • catalog_product_entity_varchar: Peran ing ngendi gambar digunakake disimpen ing kene;

lan gambar dhewe disimpen ing direktori ./pub/media/catalog/product/x/y/ngendi x и y - huruf pisanan lan kaloro saka jeneng file gambar. Contone, file image.png kudu disimpen minangka ./pub/media/catalog/product/i/m/image.png, supaya platform bisa digunakake minangka gambar nalika njlèntrèhaké produk saka katalog.

Register dikirim ing ./pub/media/catalog/product/ file media (proses nempatake file kasebut dhewe ora dibahas ing artikel iki):

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

Nalika kadhaptar, file media anyar diwenehi pengenal.

Kita nggandhengake file media sing kadhaptar karo produk sing cocog kanggo etalase standar:

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

Kita nggandhengake file media sing kadhaptar karo produk sing cocog tanpa diikat menyang etalase apa wae. Ora cetha ngendi persis data iki digunakake lan apa iku mokal kanggo ngakses data saka tabel sadurungΓ©, nanging tabel iki ana lan data ditulis kanggo nalika gambar ditambahake kanggo produk. Dadi ngono wae.

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

File media bisa digunakake kanthi peran sing beda-beda (kode atribut sing cocog dituduhake ing kurung):

  • dhasar (image)
  • Gambar cilik (small_image)
  • Gambar cilik (thumbnail)
  • Gambar Swatch (swatch_image)

Nyambungake peran menyang file media persis apa sing kedadeyan catalog_product_entity_varchar. Kode binding padha karo kode ing "Atribut produk dhasar".

Sawise nambahake gambar menyang produk ing panel admin katon kaya iki:

Magento 2: ngimpor produk langsung menyang database

Kategori

Tabel utama sing ngemot data miturut kategori:

  • catalog_category_entity: daftar kategori;
  • catalog_category_product: sambungan antarane produk lan kategori;
  • catalog_category_entity_*: Nilai atribut EAV;

Kaping pisanan, ing aplikasi Magento kosong, registri kategori ngemot 2 kategori (Aku nyepetake jeneng kolom: 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|

Kategori kanthi id=1 minangka oyod saka kabeh katalog Magento lan ora kasedhiya ing panel admin utawa ing kaca ngarep. Kategori kanthi id=2 (Kategori Default) minangka kategori root kanggo toko utama situs utama (Toko Website Utama) digawe nalika aplikasi disebarake (ndeleng. Admin / Toko / Kabeh Toko). Kajaba iku, kategori ROOT saka toko dhewe uga ora kasedhiya ing ngarep, mung subkategori sawijining.

Wiwit topik artikel iki isih ngimpor data babagan produk, aku ora bakal nggunakake entri langsung menyang database nalika nggawe kategori, nanging bakal nggunakake kelas sing diwenehake dening Magento dhewe (model lan repositori). Entri langsung menyang database mung digunakake kanggo nggandhengake produk sing diimpor karo kategori (kategori cocog karo jenenge, lan id kategori dijupuk nalika cocog):

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

Sawise nambahake link produk menyang kategori "Kategori 1" lan "Kategori 2", rincian produk ing panel admin katon kaya iki:

Magento 2: ngimpor produk langsung menyang database

Tumindak tambahan

Sawise ngimpor data rampung, sampeyan kudu ngrampungake langkah-langkah tambahan ing ngisor iki:

  • indeksasi data: nelpon ing console ./bin/magento indexer:reindex;
  • URL regenerasi kanggo produk / kategori: sampeyan bisa nggunakake ekstensi "elgentos / regenerate-katalog-urlsΒ«

Produk ing panel admin sawise nindakake tindakan tambahan:

Magento 2: ngimpor produk langsung menyang database

lan ing ngarep:

Magento 2: ngimpor produk langsung menyang database

Ringkesan

Set produk sing padha (10 potongan) kaya ing artikel sadurunge diimpor paling sethithik urutan gedhene luwih cepet (1 detik lawan 10). Kanggo ngira kacepetan kanthi luwih akurat, sampeyan butuh luwih akeh produk - sawetara atus, utawa luwih ewonan. Nanging, sanajan kanthi ukuran data input sing cilik, kita bisa nyimpulake yen panggunaan alat sing diwenehake dening Magento (model lan repositori) penting (aku nandheske - akeh!) nyepetake pangembangan fungsi sing dibutuhake, nanging ing wektu sing padha sacara signifikan (aku nandheske - akeh!) nyuda kacepetan ing data nemu menyang database.

AkibatΓ©, banyu dadi teles lan iki dudu wahyu. Nanging, saiki aku duwe kode kanggo muter lan bisa uga teka ing sawetara kesimpulan sing luwih menarik.

Source: www.habr.com