Magento 2: importimi i produkteve nga burime të jashtme

Magento është një zgjidhje e-commerce, që do të thotë se është më shumë e fokusuar në shitjen e produkteve sesa në menaxhimin e inventarit, logjistikës ose financave që i shërbejnë shitjes. Për menaxhimin e këtyre aspekteve, aplikacione të tjera (si ERP) janë më të përshtatshme. Prandaj, shpesh herë praktikisht, përdorimi i Magento kërkon integrimin e dyqanit me këto sisteme të tjera (p.sh., me 1C).

Në thelb, integrimin mund ta reduktojmë në replikimin e të dhënave sipas:

  • katalogut (produkte, kategori);
  • tĂ« dhĂ«nave tĂ« inventarit (stoku i produkteve nĂ« depo dhe çmimet);
  • klientĂ«ve;
  • porosive;

Magento ofron njĂ« klasĂ« tĂ« veçantĂ« objektesh pĂ«r manipulimin e tĂ« dhĂ«nave nĂ« bazĂ« — repotitĂ« e tij. PĂ«r shkak tĂ« natyrĂ«s specifike tĂ« Magento, shtimi i tĂ« dhĂ«nave nĂ« bazĂ« pĂ«rmes repositorĂ«ve Ă«shtĂ« i lehtĂ« pĂ«r t'u koduar, por ndodh, le tĂ« themi, ngadalĂ«. NĂ« kĂ«tĂ« publikim, shqyrtoj fazat kryesore tĂ« shtimit programatik tĂ« produktit nĂ« Magento 2 nĂ« mĂ«nyrĂ«n "klasike" — duke pĂ«rdorur klasat repo.

KlientĂ«t dhe porositĂ« zakonisht replikohen nĂ« njĂ« drejtim tjetĂ«r — nga Magento nĂ« sistemet ERP tĂ« jashtme. Prandaj, me to Ă«shtĂ« mĂ« e lehtĂ«, nga ana e Magento duhen thjesht zgjedhur tĂ« dhĂ«nat pĂ«rkatĂ«se, dhe pastaj — "nga ana jonĂ« plumbat dolĂ«n«.

Principet e regjistrimit të të dhënave në bazë

Aktualisht, krijimi i objekteve të ruajtura në bazë në mënyrë programore në Magento bëhet përmes Factory:

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

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

dhe regjistrimi nĂ« bazĂ« — pĂ«rmes Repository:

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

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

Prapproprimi me përdorimin e "Factory" dhe "Repository" mund të përdoret për të gjitha modelet kryesore në fushën e Magento 2.

Informacione bazë mbi produktin

Unë shqyrtoj strukturën e të dhënave që i përket versionit Magento 2.3. Informacioni më i thjeshtë mbi produktin ndodhet në tabelën catalog_product_entity (regjistri i produkteve):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Këtu kufizohem në një tip produkti (type_id='simple'), grupin e atributeve sipas parimeve (attribute_set_id=4) dhe injoroj atributet has_options dhe required_options. Duke qenë se atributet entity_id, created_at dhe updated_at generohen automatikisht, në thelb, për të shtuar një produkt të ri, mjafton të caktojmë sku. Bëj kështu:

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

dhe merr një përjashtim:

Vlera e atributit "Emri i Produktit" është e zbrazët. Caktoni atributin dhe provoni përsëri.

Shtoj nĂ« kĂ«rkesĂ« emrin e produktit dhe marr mesazhin se mungon atributi Çmimi. Pas shtimit tĂ« çmimit, produkti regjistrohet nĂ« bazĂ«:

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

Emri i produktit ruhet në tabelën e atributeve varchar të produktit (catalog_product_entity_varchar), çmimi - në tabelën catalog_product_entity_decimal. Para shtimit të produktit, është e këshillueshme të specifikohet qartë se po përdorim vitrinën administrativë për importimin e të dhënave:

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

Atribute shtesë

PĂ«rpunimi i atributeve shtesĂ« tĂ« produkteve me mjete Magento Ă«shtĂ« njĂ« kĂ«naqĂ«si. Modeli EAV i tĂ« dhĂ«nave pĂ«r entitetet kryesore (shih tabelĂ«n eav_entity_type) — Ă«shtĂ« njĂ« nga veçoritĂ« kyç tĂ« kĂ«saj platforme. Thjesht shtojmĂ« atributet pĂ«rkatĂ«se nĂ« modelin e produktit:

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

dhe kur ruhet modeli përmes objektit të repo-s:

$repoProd->save($prod);

atributet shtesë do të ruhen gjithashtu në tabelat përkatëse të DB-së.

Të dhënat e inventarit

Thjesht — sasia e produktit nĂ« magazinĂ«. NĂ« Magento 2.3 struktura nĂ« DB pĂ«rshkruan formatin e ruajtjes sĂ« tĂ« dhĂ«nave tĂ« inventarit, ndjeshĂ«m ndryshon nga ajo qĂ« ishte mĂ« parĂ«. MegjithatĂ«, shtimi i sasisĂ« sĂ« produktit nĂ« magazinĂ« pĂ«rmes modelit tĂ« produktit nuk Ă«shtĂ« shumĂ« mĂ« i komplikuar se shtimi i atributeve tĂ« tjera:

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

Media

zakonisht, mbështetje media e produktit për klientin në dyqan (e-commerce) ndryshon nga mbështetja media e këtij produkti për punonjësin në sistemin e brendshëm të llogaritjes (ERP). Në rastin e parë, është e dëshirueshme të tregosh "produktin përballë", në rastin e dytë, mjafton të japësh një pamje të përgjithshme të produktit. Megjithatë, transferimi i të paktën imazhit fillestar të produktit është një rast në importin e të dhënave.

Kur shtohet një imazh përmes administratës, fotografia fillimisht ruhet në një katalog përkohësor (./pub/media/tmp/catalog/product) dhe vetëm kur produkti ruhet, zhvendoset në katalogun e mediave (./pub/media/catalog/product). Gjithashtu, kur shtohet përmes administratës, imazhit i caktohen etiketat 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);

Për ndonjë arsye, media lidh vetëm pas ruajtjes paraprake të produktit dhe marrjes së tij nga repositoriumi përsëri. Dhe duhet të specifikohet atributi label kur shtohet një regjistrim në galerinë e mediave të produktit (ndryshe merrim një përjashtim Indeks i paqartë: label në .../module-catalog/Model/Product/Gallery/CreateHandler.php në linjën 516).

Kategoritë

Struktura e kategorive të dyqanit dhe aplikacionit backend shpeshherë mund të ndryshojnë ndjeshëm. Strategjitë për transferimin e të dhënave rreth kategorive dhe produkteve në to varen nga shumë faktorë. Në këtë shembull, do të ndjek këtë qasje:

  • kategoritĂ« e backend dhe dyqanit pĂ«rputhen sipas emrit;
  • nĂ«se importohet njĂ« kategori qĂ« nuk ekziston nĂ« dyqan, ajo krijohet nĂ«n kategorinĂ« kryesore (Default Category) dhe pozicionimi i saj mĂ« tej nĂ« katalogun e dyqanit pritet tĂ« bĂ«het nĂ« mĂ«nyrĂ« manuale;
  • lidhja e produktit me kategorinĂ« ndodh vetĂ«m kur krijohet nĂ« dyqan (nĂ« importin e parĂ«);

Informacioni kryesor rreth kategorisë ndodhet në tabelën catalog_category_entity (katalogu i kategorive). Krijimi i një kategorie në Magento:

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

Lidhja e produktit me kategorinë bëhet sipas ID-së së kategorisë dhe SKU-së së produktit:

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

Përveç kësaj

Të shkruash kod për të shtuar një produkt në Magento 2 në mënyrë programore nuk është shumë e vështirë. Të gjitha informatat e mëposhtme i kam përmbledhur në një modul demo "flancer32/mage2_ext_demo_import". Në modul ka vetëm një komandë konsolë fl32:import:prod, e cila importon produktet e përshkruara në skedarin JSON "./etc/data/products.json«:

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

Imazhet për import ndodhen në katalogun .\/etc\/data\/img.

Koha e importit për 10 produkte në këtë mënyrë është rreth 10 sekonda në laptopin tim. Nëse e zhvillojmë këtë ide, lehtë arrijmë në përfundimin se në orë mund të importojmë rreth 3600 produkte, dhe për importimin e 100K produkteve mund të nevojiten rreth 30 orë. Zëvendësimi i laptopit me një server ka mundësinë ta përmirësojë situatën. Mund të jetë madje disa herë më i shpejtë. Por jo në mënyrë dramatike. Ndoshta kjo ngadalësi është një nga arsyet për shfaqjen e projektit magento/async-import.

Një zgjidhje drastike për rritjen e shpejtësisë së importit mund të jetë shkrimi direkt në bazën e të dhënave, por në këtë rast humbasin të gjitha "avantazhet" që lidhen me zgjerueshmërinë e Magento - do të duhet t'i bësh vetë të gjitha "zgjerimet". Megjithatë, ia vlen. Nëse është e mundur, do të shqyrtoj qasjen me shkrim të drejtpërdrejtë në DB në artikullin e ardhshëm.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster