Magento 2: importarea produselor din surse externe

Magento este o soluție de comerț electronic, adică vizează mai mult vânzarea produselor decât depozitarea, logistica sau contabilitatea financiară care însoțesc vânzările. Alte aplicații (de exemplu, sistemele ERP) sunt mai potrivite pentru aplicațiile însoțitoare. Prin urmare, destul de des în practica utilizării Magento apare sarcina de a integra un magazin cu aceste alte sisteme (de exemplu, 1C).

În general, integrarea poate fi redusă la replicarea datelor prin:

  • catalog (produse, categorii);
  • datele de stoc (solurile produselor în depozite și prețuri);
  • clienti;
  • Comenzi;

Magento oferă o clasă separată de obiecte pentru manipularea datelor din baza de date - depozite. Datorită specificului Magento, adăugarea datelor la baza de date prin depozite este ușor de codificat, dar este, să spunem, lent. În această publicație, iau în considerare principalele etape ale adăugării programatice a unui produs la Magento 2 în mod „clasic” - folosind clase repo.

Clienții și comenzile sunt de obicei replicate în cealaltă direcție - de la Magento la sisteme ERP externe. Prin urmare, este mai simplu cu ei, pe partea Magento trebuie doar să selectați datele corespunzătoare, apoi „gloanțe au zburat din partea noastră“.

Principii de înregistrare a datelor într-o bază de date

În acest moment, crearea obiectelor salvate în baza de date în mod programatic în Magento se face prin intermediul Fabrică:

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

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

iar scrierea în baza de date se face prin Repertoriu:

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

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

Abordarea „Factory” și „Repository” pot fi utilizate pentru toate modelele majore din domeniul Magento 2.

Informații de bază despre produs

Mă uit la o structură de date care se potrivește cu versiunea Magento 2.3. Cele mai de bază informații despre produs sunt în tabel catalog_product_entity (registrul produselor):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Sunt limitat la un singur tip de produs (type_id='simple'), un set de atribute implicite (attribute_set_id=4) și ignorați atributele has_options и required_options. Din moment ce atributele entity_id, created_at и updated_at sunt generate automat, apoi, de fapt, pentru a adăuga un nou produs, trebuie doar să setăm sku. Eu fac asta:

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

și primesc o excepție:

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

Adaug numele produsului la cerere și primesc un mesaj că atributul lipsește Price. După adăugarea prețului, produsul este adăugat în baza de date:

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

Numele produsului este stocat în tabelul de atribute varchar al produsului (catalog_product_entity_varchar), preț - în tabel catalog_product_entity_decimal. Înainte de a adăuga un produs, este recomandabil să indicați în mod explicit că folosim vitrina administrativă pentru a importa date:

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

Atribute suplimentare

Procesarea atributelor suplimentare de produs folosind Magento este o plăcere. Model de date EAV pentru principalele entități (a se vedea tabelul eav_entity_type) este una dintre caracteristicile cheie ale acestei platforme. Pur și simplu adăugăm atributele adecvate modelului de produs:

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

și la salvarea modelului prin obiectul repo:

$repoProd->save($prod);

atributele suplimentare vor fi stocate și în tabelele corespunzătoare ale bazei de date.

Date de inventar

În termeni simpli - cantitatea de produs în stoc. În Magento 2.3, structurile din baza de date care descriu formatul pentru stocarea datelor de inventar sunt semnificativ diferite din ceea ce s-a întâmplat înainte. Cu toate acestea, adăugarea cantității de produs în stoc prin modelul de produs nu este mult mai dificilă decât adăugarea altor atribute:

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

Mass-media

De regulă, suportul media pentru un produs pentru un client dintr-un magazin (comerț electronic) diferă de suportul media pentru același produs pentru un angajat într-un sistem de contabilitate intern (ERP). În primul caz, este recomandabil să arătați produsul față în față; în al doilea, este suficient să oferiți o idee generală a produsului. Cu toate acestea, transferul cel puțin a imaginii primare a unui produs este destul de comun. case la importul de date.

Când adăugați o imagine prin panoul de administrare, imaginea este mai întâi salvată într-un director temporar (./pub/media/tmp/catalog/product) și numai la salvarea produsului este mutat în directorul media (./pub/media/catalog/product). De asemenea, atunci când este adăugată prin panoul de administrare, imaginea este etichetată 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);

Din anumite motive, media este conectată numai după salvarea produsului și preluarea acestuia din nou din depozit. Și trebuie să specificați atributul label atunci când adăugați o intrare în galeria media de produse (în caz contrar, obținem o excepție Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

Categorie

Adesea, structura de categorii a magazinului și aplicația backend sau plasarea produselor în acestea pot diferi semnificativ. Strategiile pentru migrarea datelor despre categorii și produse din cadrul acestora depind de mulți factori. În acest exemplu mă țin de următoarele:

  • categoriile de backend și magazine sunt comparate după nume;
  • dacă este importată o categorie care nu se află în magazin, atunci aceasta este creată sub categoria rădăcină (Default Category) iar poziționarea ulterioară a acestuia în catalogul magazinului este asumată manual;
  • un produs este atribuit unei categorii numai atunci când este creat în magazin (primul import);

Informațiile de bază despre categorie sunt în tabel catalog_category_entity (catalog de categorii). Crearea unei categorii în Magento:

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

Conectarea unui produs la o categorie se realizează folosind ID-ul categoriei și codul SKU al produsului:

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

În total

Scrierea codului pentru a adăuga un produs în mod programatic la Magento 2 este destul de ușoară. Am combinat tot ce s-a spus mai sus într-un modul demonstrativ „flancer32/mage2_ext_demo_import". Există o singură comandă de consolă în modul fl32:import:prod, care importă produsele descrise în fișierul JSON "./etc/data/products.json„:

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

Pozele pentru import sunt in catalog ./etc/data/img.

Timpul pentru a importa 10 produse folosind această metodă este de aproximativ 10 secunde pe laptopul meu. Dacă dezvoltăm această idee în continuare, este ușor să ajungem la concluzia că aproximativ 3600 de produse pot fi importate pe oră și poate dura aproximativ 100 de ore pentru a importa 30 de produse. Înlocuirea unui laptop cu un server vă permite să neteziți oarecum situația. Poate chiar de mai multe ori. Dar nu după ordine de mărime. Poate că această viteză și încetineală este într-o oarecare măsură unul dintre motivele apariției proiectului magento/async-import.

O soluție radicală pentru creșterea vitezei de import ar putea fi intrarea directă în baza de date, dar în acest caz toate „bunătățile” privind extensibilitatea Magento sunt pierdute - va trebui să faceți singur totul „avansat”. Cu toate acestea, merită. Dacă funcționează, voi lua în considerare abordarea cu scriere directă în baza de date în articolul următor.

Sursa: www.habr.com

Adauga un comentariu