Magento 2: Mengimport Produk daripada Sumber Luaran

Magento ialah penyelesaian e-dagang, i.e. lebih bertujuan untuk menjual produk daripada pergudangan, logistik atau perakaunan kewangan yang mengiringi jualan. Aplikasi lain (contohnya, sistem ERP) lebih sesuai untuk aplikasi yang disertakan. Oleh itu, agak kerap dalam amalan menggunakan Magento tugas untuk mengintegrasikan kedai dengan sistem lain ini (contohnya, 1C) timbul.

Pada umumnya, penyepaduan boleh dikurangkan kepada replikasi data dengan:

  • katalog (produk, kategori);
  • data inventori (baki produk dalam gudang dan harga);
  • pelanggan;
  • pesanan;

Magento menawarkan kelas objek yang berasingan untuk memanipulasi data dalam pangkalan data - repositori. Disebabkan oleh kekhususan Magento, menambahkan data ke pangkalan data melalui repositori adalah mudah untuk dikodkan, tetapi ia adalah, katakan, perlahan. Dalam penerbitan ini, saya mempertimbangkan peringkat utama menambahkan produk secara pemrograman pada Magento 2 dengan cara "klasik" - menggunakan kelas repo.

Pelanggan dan pesanan biasanya direplikasi ke arah lain - dari Magento ke sistem ERP luaran. Oleh itu, lebih mudah dengan mereka, di sebelah Magento anda hanya perlu memilih data yang sesuai, dan kemudian "peluru terbang keluar dari pihak kami".

Prinsip merekod data ke dalam pangkalan data

Pada masa ini, mencipta objek yang disimpan dalam pangkalan data secara pengaturcaraan dalam Magento dilakukan melalui kilang:

function __construct (MagentoCmsModelBlockFactory $blockFactory) {
    $this->blockFactory = $blockFactory;
}

/** @var MagentoCmsModelBlock $block */
$block = $this->blockFactory->create();

dan menulis ke pangkalan data dilakukan melalui Repositori:

function __construct (MagentoCmsApiBlockRepositoryInterface $blockRepo) {
    $this->blockRepo = $blockRepo;
}

$this->blockRepo->save($block);

Pendekatan "Kilang" dan "Repositori" boleh digunakan untuk semua model utama dalam domain Magento 2.

Maklumat Produk Asas

Saya sedang melihat struktur data yang sepadan dengan versi Magento 2.3. Maklumat paling asas tentang produk adalah dalam jadual catalog_product_entity (pendaftaran produk):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Saya terhad kepada satu jenis produk (type_id='simple'), satu set atribut lalai (attribute_set_id=4) dan abaikan atribut has_options ΠΈ required_options. Sejak sifat-sifat entity_id, created_at ΠΈ updated_at dijana secara automatik, maka, sebenarnya, untuk menambah produk baru, kita hanya perlu menetapkan sku. Saya melakukan ini:

/** @var MagentoCatalogApiDataProductInterfaceFactory $factProd */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
/** @var MagentoCatalogApiDataProductInterface $prod */
$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$repoProd->save($prod);

dan saya mendapat pengecualian:

The "Product Name" attribute value is empty. Set the attribute and try again.

Saya menambah nama produk pada permintaan dan mendapat mesej bahawa atribut itu tiada Price. Selepas menambah harga, produk ditambah ke pangkalan data:

$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$prod->setName($name);
$prod->setPrice($price);
$repoProd->save($prod);

Nama produk disimpan dalam jadual atribut varchar produk (catalog_product_entity_varchar), harga - dalam jadual catalog_product_entity_decimal. Sebelum menambah produk, adalah dinasihatkan untuk menyatakan dengan jelas bahawa kami menggunakan etalase pentadbiran untuk mengimport data:

/** @var MagentoStoreModelStoreManagerInterface $manStore */
$manStore->setCurrentStore(0);

Atribut Tambahan

Memproses atribut produk tambahan menggunakan Magento adalah suatu keseronokan. Model data EAV untuk entiti utama (lihat jadual eav_entity_type) adalah salah satu ciri utama platform ini. Kami hanya menambah atribut yang sesuai pada model produk:

$prodEntity->setData('description', $desc);
$prodEntity->setData('short_description', $desc_short);
// ΠΈΠ»ΠΈ
$prodEntity->setDescription($desc);
$prodEntity->setShortDescription($desc_short);

dan apabila menyimpan model melalui objek repo:

$repoProd->save($prod);

atribut tambahan juga akan disimpan dalam jadual pangkalan data yang sepadan.

Data inventori

Secara ringkas - jumlah produk dalam stok. Dalam Magento 2.3, struktur dalam pangkalan data yang menerangkan format untuk menyimpan data inventori ialah ketara berbeza daripada apa yang berlaku sebelum ini. Walau bagaimanapun, menambah kuantiti produk dalam stok melalui model produk tidaklah lebih sukar daripada menambah atribut lain:

/** @var MagentoCatalogModelProduct $prodEntity */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
$inventory = [
    'is_in_stock' => true,
    'qty' => 1234
];
$prodEntity->setData('quantity_and_stock_status', $inventory);
$repoProd->save($prodEntity);

Media

Sebagai peraturan, sokongan media untuk produk untuk pelanggan di kedai (e-dagang) berbeza daripada sokongan media untuk produk yang sama untuk pekerja dalam sistem perakaunan dalaman (ERP). Dalam kes pertama, adalah dinasihatkan untuk menunjukkan produk secara bersemuka; dalam kes kedua, sudah cukup untuk memberikan gambaran umum tentang produk. Walau bagaimanapun, memindahkan sekurang-kurangnya imej utama produk adalah perkara biasa. case apabila mengimport data.

Apabila menambah imej melalui panel pentadbir, imej pertama kali disimpan dalam direktori sementara (./pub/media/tmp/catalog/product) dan hanya apabila menyimpan produk dialihkan ke direktori media (./pub/media/catalog/product). Selain itu, apabila ditambah melalui panel pentadbir, imej ditandakan image, small_image, thumbnail, swatch_image.

/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
/** @var MagentoCatalogModelProductGalleryCreateHandler $hndlGalleryCreate */
/* $imagePath = '/path/to/file.png';  $imagePathRelative = '/f/i/file.png' */
$imagePathRelative = $this->imagePlaceToTmpMedia($imagePath);
/* reload product with gallery data */
$product = $repoProd->get($sku);
/* add image to product's gallery */
$gallery['images'][] = [
    'file' => $imagePathRelative,
    'media_type' => 'image'
    'label' => ''
];
$product->setData('media_gallery', $gallery);
/* set usage areas */
$product->setData('image', $imagePathRelative);
$product->setData('small_image', $imagePathRelative);
$product->setData('thumbnail', $imagePathRelative);
$product->setData('swatch_image', $imagePathRelative);
/* create product's gallery */
$hndlGalleryCreate->execute($product);

Atas sebab tertentu, media dipautkan hanya selepas pertama kali menyimpan produk dan mendapatkannya daripada repositori. Dan anda perlu menentukan atribut label apabila menambah entri ke galeri media produk (jika tidak, kami mendapat pengecualian Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

ΠšΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ

Selalunya, struktur kategori kedai dan aplikasi bahagian belakang atau penempatan produk di dalamnya boleh berbeza dengan ketara. Strategi untuk memindahkan data tentang kategori dan produk di dalamnya bergantung pada banyak faktor. Dalam contoh ini saya berpegang kepada perkara berikut:

  • bahagian belakang dan kategori kedai dibandingkan dengan nama;
  • jika kategori diimport yang tiada dalam kedai, maka ia dibuat di bawah kategori akar (Default Category) dan kedudukannya selanjutnya dalam katalog kedai diandaikan secara manual;
  • produk diperuntukkan kepada kategori hanya apabila ia dibuat di kedai (import pertama);

Maklumat asas tentang kategori terdapat dalam jadual catalog_category_entity (katalog kategori). Mencipta kategori dalam Magento:

/** @var MagentoCatalogApiDataCategoryInterfaceFactory $factCat */
/** @var MagentoCatalogApiCategoryRepositoryInterface $repoCat */
$cat = $factCat->create();
$cat->setName($name);
$cat->setIsActive(true);
$repoCat->save($cat);

Memautkan produk kepada kategori dijalankan menggunakan ID kategori dan SKU produk:

/** @var MagentoCatalogModelCategoryProductLinkFactory $factCatProdLink */
/** @var MagentoCatalogApiCategoryLinkRepositoryInterface $repoCatLink */
$link = $factCatProdLink->create();
$link->setCategoryId($catMageId);
$link->setSku($prodSku);
$repoCatLink->save($link);

Dalam jumlah

Menulis kod untuk menambah produk secara pengaturcaraan pada Magento 2 agak mudah. Saya telah menggabungkan semua yang dinyatakan di atas ke dalam modul demo "flancer32/mage2_ext_demo_import". Terdapat hanya satu arahan konsol dalam modul fl32:import:prod, yang mengimport produk yang diterangkan dalam fail JSON "./etc/data/products.json":

[
  {
    "sku": "...",
    "name": "...",
    "desc": "...",
    "desc_short": "...",
    "price": ...,
    "qty": ...,
    "categories": ["..."],
    "image_path": "..."
  }
]

Gambar untuk import ada dalam katalog ./etc/data/img.

Masa untuk mengimport 10 produk menggunakan kaedah ini adalah kira-kira 10 saat pada komputer riba saya. Jika kita mengembangkan lagi idea ini, mudah untuk membuat kesimpulan bahawa kira-kira 3600 produk boleh diimport setiap jam, dan ia boleh mengambil masa kira-kira 100 jam untuk mengimport 30K produk. Menggantikan komputer riba dengan pelayan membolehkan anda melancarkan sedikit keadaan. Mungkin juga beberapa kali. Tetapi bukan mengikut urutan magnitud. Mungkin kepantasan dan kelambatan ini sedikit sebanyak menjadi salah satu punca kemunculan projek tersebut magento/async-import.

Penyelesaian radikal untuk meningkatkan kelajuan import boleh menjadi kemasukan terus ke dalam pangkalan data, tetapi dalam kes ini semua "barangan" mengenai kebolehlanjutan Magento hilang - anda perlu melakukan semuanya "maju" sendiri. Walau bagaimanapun, ia berbaloi. Jika ia berjaya, saya akan mempertimbangkan pendekatan dengan menulis terus ke pangkalan data dalam artikel seterusnya.

Sumber: www.habr.com

Tambah komen