В Artikel sebelumnya Saya menjelaskan proses mengimpor produk ke Magento 2 dengan cara biasa - melalui model dan repositori. Cara biasa memiliki kecepatan pengolahan data yang sangat rendah. Laptop saya menghasilkan sekitar satu produk per detik. Dalam kelanjutan ini, saya mempertimbangkan cara alternatif untuk mengimpor produk - dengan masuk langsung ke database, melewati mekanisme standar Magento 2 (model, pabrik, repositori). Urutan langkah-langkah mengimpor produk dapat disesuaikan dengan bahasa pemrograman apa pun yang dapat bekerja dengan MySQL.
Penolakan tanggung jawab: Magento memiliki fungsionalitas siap pakai untuk impor data dan, kemungkinan besar, itu sudah cukup untuk Anda. Namun, jika Anda memerlukan kontrol lebih lengkap atas proses impor, tidak terbatas pada menyiapkan file CSV untuk apa yang Anda miliki, selamat datang di cat.
Kode hasil penulisan kedua artikel tersebut dapat dilihat pada modul Magento”flancer32/mage2_ext_demo_import". Berikut beberapa batasan yang saya ikuti untuk menyederhanakan kode modul demo:
Produk hanya dibuat, bukan diperbarui.
Satu gudang
Hanya nama kategori yang diimpor, tanpa strukturnya
Struktur data mematuhi versi 2.3
JSON untuk mengimpor satu produk:
{
"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"
}
Ikhtisar tahapan utama impor
pendaftaran produk itu sendiri
hubungan antara produk dan situs web
atribut produk dasar (EAV)
data inventaris (jumlah produk dalam stok)
media (gambar)
koneksi dengan kategori katalog
Registrasi produk
Informasi produk dasar dapat ditemukan di 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 minimum yang diperlukan untuk membuat entri di registri produk adalah:
attribute_set_id
sku
tambahan:
type_id — jika kita tidak menentukannya, maka 'sederhana' akan digunakan
Untuk menulis langsung ke database, saya menggunakan adaptor DB Magento itu sendiri:
Produk yang baru didaftarkan belum memiliki nama atau deskripsi. Semua ini dilakukan melalui Atribut EAV. Berikut daftar atribut dasar produk yang diperlukan agar produk dapat ditampilkan dengan benar di bagian depan:
name
price
description
short_description
status
tax_class_id
url_key
visibility
Atribut terpisah ditambahkan ke produk seperti ini (detail untuk mendapatkan pengidentifikasi dan jenis atribut dari kodenya dihilangkan):
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);
}
}
Dengan menggunakan kode atribut, kami menentukan id dan tipe datanya (datetime, decimal, int, text, varchar), lalu tulis data untuk jendela administratif ke dalam tabel yang sesuai (store_id = 0).
Setelah menambahkan atribut di atas ke produk, Anda mendapatkan gambar ini di panel admin:
Data inventaris
Mulai dari versi 2.3 di Magento, terdapat dua kumpulan tabel paralel yang menyediakan penyimpanan informasi inventaris (kuantitas produk):
cataloginventory_*: struktur lama;
inventory_*: struktur baru (MSI - Inventaris Multi Sumber);
Anda perlu menambahkan data inventaris ke kedua struktur, karena struktur baru belum sepenuhnya independen dari struktur lama (sangat mungkin terjadi default gudang dalam struktur baru sebuah meja terlibat cataloginventory_stock_status sebagai inventory_stock_1).
inventaris katalog_
Saat menerapkan Magneto 2.3 awalnya kami memiliki 2 entri store_website, yang sesuai dengan dua situs - administratif dan klien utama:
Artinya, dalam struktur lama kita hanya ada satu “gudang” (stock) dan ditautkan ke situs web administratif. Menambahkan yang baru melalui panel admin sources/stocks di MSI (struktur baru) tidak menghasilkan entri baru cataloginventory_stock.
Data inventaris produk dalam struktur lama awalnya dicatat dalam tabel:
cataloginventory_stock_item
cataloginventory_stock_status
kataloginventory_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);
}
kataloginventory_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_
Awalnya, struktur baru untuk menyimpan data inventaris berisi 1"sumber'(inventory_source):
«Источник» mewakili penyimpanan fisik produk (catatan berisi koordinat fisik dan alamat surat). "Gudang"adalah gabungan logis dari beberapa "sumber" (inventory_source_stock_link)
pada tingkat di mana koneksi ke saluran penjualan terjadi (inventory_stock_sales_channel)
type |code|stock_id|
-------|----|--------|
website|base| 1|
Dilihat dari struktur datanya, diasumsikan berbagai jenis saluran penjualan, tetapi secara default hanya koneksi “saham"-"situs web"(tautan ke situs web mengikuti kode situs web - base).
Satu "gudang"dapat dihubungkan ke beberapa"ke sumber"dan satu "sumber" - ke beberapa "gudang“(hubungan banyak ke banyak). Pengecualian adalah default "sumber"Dan"gudang". Mereka tidak ditautkan kembali ke entitas lain (batasan pada tingkat kode - kesalahan “Tidak dapat menyimpan link terkait Sumber Default atau Stok Default"). Detail lebih lanjut tentang struktur MSI di Magento 2 dapat ditemukan di artikel “Sistem manajemen gudang menggunakan CQRS dan Event Sourcing. Desain".
Saya akan menggunakan konfigurasi default dan menambahkan semua informasi inventaris ke sumbernya default, yang terlibat dalam saluran penjualan yang terkait dengan situs web dengan kode tersebut base (sesuai dengan bagian depan toko - lihat store_website):
Setelah menambahkan data inventaris produk di panel admin, Anda mendapatkan gambar ini:
Media
Saat menambahkan gambar ke produk secara “manual” melalui panel admin, informasi yang relevan dicatat dalam tabel berikut:
catalog_product_entity_media_gallery: registri media (file gambar dan video);
catalog_product_entity_media_gallery_value: menghubungkan media dengan produk dan etalase (lokalisasi);
catalog_product_entity_media_gallery_value_to_entity: menghubungkan media ke produk saja (mungkin konten media default untuk produk);
catalog_product_entity_varchar: Peran di mana gambar tersebut digunakan disimpan di sini;
dan gambarnya sendiri disimpan ke direktori ./pub/media/catalog/product/x/y/Dimana x и y — huruf pertama dan kedua dari nama file gambar. Misalnya, berkas image.png harus disimpan sebagai ./pub/media/catalog/product/i/m/image.png, sehingga platform dapat menggunakannya sebagai gambar saat mendeskripsikan produk dari katalog.
katalog_produk_entitas_media_galeri
Daftar diposting di ./pub/media/catalog/product/ file media (proses penempatan file itu sendiri tidak dibahas dalam artikel ini):
Kami mengaitkan file media terdaftar dengan produk terkait tanpa terikat ke etalase mana pun. Tidak jelas di mana tepatnya data ini digunakan dan mengapa data dari tabel sebelumnya tidak dapat diakses, tetapi tabel ini ada dan data ditulis ke dalamnya ketika gambar ditambahkan ke produk. Jadi itu saja.
File media dapat digunakan dengan peran berbeda (kode atribut terkait ditunjukkan dalam tanda kurung):
Basis(image)
Gambar Kecil (small_image)
Gambar kecil (thumbnail)
Contoh Gambar (swatch_image)
Menautkan peran ke file media adalah hal yang persis terjadi catalog_product_entity_varchar. Kode pengikatannya mirip dengan kode di "Atribut produk dasar".
Setelah menambahkan gambar ke produk di panel admin tampilannya seperti ini:
Kategori
Tabel utama berisi data berdasarkan kategori:
catalog_category_entity: daftar kategori;
catalog_category_product: hubungan antara produk dan kategori;
catalog_category_entity_*: nilai atribut EAV;
Awalnya pada aplikasi Magento yang kosong, registry kategori berisi 2 kategori (saya persingkat nama kolomnya: crt - created_at, upd - updated_at):
Kategori dengan id=1 adalah akar dari keseluruhan katalog Magento dan tidak tersedia di panel admin atau di halaman depan. Kategori dengan id=2 (Default Kategori) adalah kategori akar untuk penyimpanan utama situs utama (Toko Situs Web Utama) dibuat saat aplikasi dikerahkan (lihat. Admin / Toko / Semua Toko). Selain itu, kategori root dari toko itu sendiri juga tidak tersedia di bagian depan, hanya subkategorinya saja.
Karena topik artikel ini masih mengimpor data produk, saya tidak akan menggunakan entri langsung ke database saat membuat kategori, tetapi akan menggunakan kelas yang disediakan oleh Magento sendiri (model dan repositori). Entri langsung ke database hanya digunakan untuk mengaitkan produk yang diimpor dengan suatu kategori (kategori dicocokkan berdasarkan namanya, dan id kategori diambil selama pencocokan):
Produk di panel admin setelah melakukan tindakan tambahan:
dan di depan:
Ringkasan
Kumpulan produk yang sama (10 buah) seperti pada artikel sebelumnya diimpor setidaknya dengan urutan besarnya lebih cepat (1 detik versus 10). Untuk memperkirakan kecepatan dengan lebih akurat, Anda memerlukan jumlah produk yang lebih banyak - beberapa ratus, atau bahkan ribuan. Namun, bahkan dengan ukuran data masukan yang kecil, kita dapat menyimpulkan bahwa penggunaan alat yang disediakan oleh Magento (model dan repositori) adalah signifikan (saya tekankan - banyak!) mempercepat pengembangan fungsionalitas yang diperlukan, tetapi pada saat yang sama secara signifikan (saya tekankan - banyak!) mengurangi kecepatan masuknya data ke database.
Akibatnya air menjadi basah dan ini bukan wahyu. Namun, sekarang saya memiliki kode untuk dimainkan dan mungkin sampai pada beberapa kesimpulan yang lebih menarik.