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 -
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
function __construct (MagentoCmsModelBlockFactory $blockFactory) {
$this->blockFactory = $blockFactory;
}
/** @var MagentoCmsModelBlock $block */
$block = $this->blockFactory->create();
iar scrierea în baza de date se face prin
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
/** @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 „fl32:import:prod
, care importă produsele descrise în fișierul 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
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