Magento 2: import af produkter fra eksterne kilder

Magento er en e-handelsløsning, dvs. er mere rettet mod at sælge produkter end på lager, logistik eller finansielt regnskab i forbindelse med salg. Andre applikationer (f.eks. ERP-systemer) er bedre egnede til ledsagende applikationer. Derfor opstår ret ofte i praksis med at bruge Magento opgaven med at integrere en butik med disse andre systemer (for eksempel 1C).

I det store og hele kan integration reduceres til datareplikering ved at:

  • katalog (produkter, kategorier);
  • lagerdata (produktbalancer i lagre og priser);
  • kunder;
  • Ordre:% s;

Magento tilbyder en separat klasse af objekter til at manipulere data i databasen - depoter. På grund af Magentos specifikationer er tilføjelse af data til databasen gennem repositories let at kode, men det er, lad os sige, langsomt. I denne publikation overvejer jeg de vigtigste stadier af programmatisk tilføjelse af et produkt til Magento 2 på den "klassiske" måde - ved hjælp af repo-klasser.

Kunder og ordrer replikeres normalt i den anden retning - fra Magento til eksterne ERP-systemer. Derfor er det nemmere med dem, på Magento-siden skal du bare vælge de relevante data, og derefter "kugler fløj ud fra vores side".

Principper for registrering af data i en database

I øjeblikket er oprettelse af objekter gemt i databasen programmatisk i Magento færdig Fabrik:

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

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

og skrivning til databasen sker igennem Repository:

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

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

"Factory" og "Repository" tilgangen kan bruges til alle større modeller i Magento 2 domænet.

Grundlæggende produktinformation

Jeg kigger på en datastruktur, der matcher Magento 2.3-versionen. Den mest grundlæggende information om produktet er i tabellen catalog_product_entity (produktregister):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Jeg er begrænset til én type produkt (type_id='simple'), et sæt standardattributter (attribute_set_id=4) og ignorer attributter has_options и required_options. Siden attributterne entity_id, created_at и updated_at genereres automatisk, så i virkeligheden, for at tilføje et nyt produkt, skal vi bare indstille sku. Jeg gør dette:

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

og jeg får en undtagelse:

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

Jeg tilføjer produktnavnet til anmodningen og får en besked om, at attributten mangler Price. Efter tilføjelse af prisen tilføjes produktet til databasen:

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

Produktnavnet gemmes i produkt varchar-attributtabellen (catalog_product_entity_varchar), pris - i tabellen catalog_product_entity_decimal. Før du tilføjer et produkt, er det tilrådeligt at angive, at vi bruger den administrative butiksfacade til at importere data:

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

Yderligere attributter

Det er en fornøjelse at behandle yderligere produktattributter ved hjælp af Magento. EAV-datamodel for hovedenheder (se tabel eav_entity_type) er en af ​​nøglefunktionerne i denne platform. Vi tilføjer blot de relevante attributter til produktmodellen:

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

og når du gemmer modellen via repo-objektet:

$repoProd->save($prod);

yderligere attributter vil også blive gemt i de tilsvarende databasetabeller.

Lagerdata

Enkelt sagt - mængden af ​​produkt på lager. I Magento 2.3 er strukturer i databasen, der beskriver formatet til lagring af lagerdata væsentligt anderledes fra hvad der skete før. Men at tilføje mængden af ​​et produkt på lager via produktmodellen er ikke meget sværere end at tilføje andre attributter:

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

Medier

Mediesupport til et produkt til en kunde i en butik (e-handel) adskiller sig som udgangspunkt fra mediesupport til samme produkt til en medarbejder i et internt regnskabssystem (ERP). I det første tilfælde er det tilrådeligt at vise produktet ansigt til ansigt; i det andet er det nok til at give en generel idé om produktet. Det er dog ret almindeligt at overføre mindst det primære billede af et produkt. case ved import af data.

Når du tilføjer et billede gennem administrationspanelet, gemmes billedet først i en midlertidig mappe (./pub/media/tmp/catalog/product) og kun når du gemmer produktet flyttes til mediebiblioteket (./pub/media/catalog/product). Når det tilføjes via administratorpanelet, er billedet også tagget 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);

Af en eller anden grund linkes mediet først efter først at have gemt produktet og hentet det fra lageret igen. Og du skal angive attributten label når du tilføjer en post til produktmediegalleriet (ellers får vi en undtagelse Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

kategori

Ofte kan kategoristrukturen i butikken og backend-applikationen eller placeringen af ​​produkter i dem variere betydeligt. Strategier til migrering af data om kategorier og produkter inden for dem afhænger af mange faktorer. I dette eksempel holder jeg mig til følgende:

  • backend- og butikskategorier sammenlignes efter navn;
  • hvis der importeres en kategori, som ikke er i butikken, oprettes den under rodkategorien (Default Category) og dens videre placering i butikskataloget antages manuelt;
  • et produkt tildeles kun en kategori, når det er oprettet i butikken (første import);

Grundlæggende oplysninger om kategorien er i tabellen catalog_category_entity (katalog over kategorier). Oprettelse af en kategori i Magento:

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

Tilknytning af et produkt til en kategori udføres ved hjælp af kategori-id og produkt-SKU:

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

I alt

Det er ret nemt at skrive kode for at tilføje et produkt programmatisk til Magento 2. Jeg har kombineret alt nævnt ovenfor til et demomodul "flancer32/mage2_ext_demo_import". Der er kun én konsolkommando i modulet fl32:import:prod, som importerer produkterne beskrevet i JSON-filen "./etc/data/products.json":

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

Billeder til import er i kataloget ./etc/data/img.

Tiden til at importere 10 produkter ved hjælp af denne metode er omkring 10 sekunder på min bærbare computer. Hvis vi videreudvikler denne idé, er det let at komme til den konklusion, at der kan importeres omkring 3600 produkter i timen, og det kan tage omkring 100 timer at importere 30K produkter. Udskiftning af en bærbar computer med en server giver dig mulighed for at udjævne situationen noget. Måske endda flere gange. Men ikke i størrelsesordener. Måske er denne hastighed og langsommelighed til en vis grad en af ​​årsagerne til projektets opståen magento/async-import.

En radikal løsning til at øge importhastigheden kunne være direkte adgang til databasen, men i dette tilfælde går alle "godbidderne" vedrørende Magentos udvidelsesmuligheder tabt - du bliver nødt til at gøre alt "avanceret" selv. Det er dog det værd. Hvis det lykkes, vil jeg overveje tilgangen med direkte skrivning til databasen i næste artikel.

Kilde: www.habr.com

Tilføj en kommentar