Magento 2: Importere produkter fra eksterne kilder

Magento er en e-handelsløsning, dvs. er mer rettet mot å selge produkter enn på lager, logistikk eller finansregnskap som følger med salg. Andre applikasjoner (for eksempel ERP-systemer) er bedre egnet for tilhørende applikasjoner. Derfor, ganske ofte i praksisen med å bruke Magento, oppstår oppgaven med å integrere en butikk med disse andre systemene (for eksempel 1C).

Stort sett kan integrasjon reduseres til datareplikering ved å:

  • katalog (produkter, kategorier);
  • lagerdata (produktbalanser i varehus og priser);
  • klienter;
  • bestillinger;

Magento tilbyr en egen klasse med objekter for å manipulere data i databasen - depoter. På grunn av spesifikasjonene til Magento er det enkelt å kode å legge til data til databasen gjennom depoter, men det er, la oss si, tregt. I denne publikasjonen tar jeg for meg hovedstadiene ved å programmatisk legge til et produkt til Magento 2 på den "klassiske" måten - ved å bruke repo-klasser.

Kunder og bestillinger replikeres vanligvis i den andre retningen – fra Magento til eksterne ERP-systemer. Derfor er det enklere med dem, på Magento-siden trenger du bare å velge riktige data, og deretter "kuler fløy ut fra vår side".

Prinsipper for å registrere data i en database

For øyeblikket er det ferdig å lage objekter som er lagret i databasen programmatisk i Magento Fabrikk:

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

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

og skriving til databasen gjøres gjennom Oppbevaringssted:

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

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

Tilnærmingen "Factory" og "Repository" kan brukes for alle hovedmodeller i Magento 2-domenet.

Grunnleggende produktinformasjon

Jeg ser på en datastruktur som samsvarer med Magento 2.3-versjonen. Den mest grunnleggende informasjonen 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 begrenset til én type produkt (type_id='simple'), et sett med standardattributter (attribute_set_id=4) og ignorer attributter has_options и required_options. Siden attributtene entity_id, created_at и updated_at genereres automatisk, så, faktisk, for å legge til et nytt produkt, trenger vi bare å stille inn sku. Jeg gjø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 et unntak:

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

Jeg legger til produktnavnet i forespørselen og får en melding om at attributtet mangler Price. Etter å ha lagt til prisen, legges produktet til i databasen:

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

Produktnavnet er lagret i produkt varchar attributttabell (catalog_product_entity_varchar), pris - i tabellen catalog_product_entity_decimal. Før du legger til et produkt, er det tilrådelig å eksplisitt angi at vi bruker den administrative butikkfronten til å importere data:

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

Ytterligere attributter

Å behandle ytterligere produktattributter ved å bruke Magento er en fornøyelse. EAV-datamodell for hovedenheter (se tabell eav_entity_type) er en av nøkkelfunksjonene til denne plattformen. Vi legger ganske enkelt til de riktige attributtene til produktmodellen:

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

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

$repoProd->save($prod);

tilleggsattributter vil også bli lagret i de tilsvarende databasetabellene.

Inventardata

Enkelt sagt - mengden produkt på lager. I Magento 2.3 er strukturer i databasen som beskriver formatet for lagring av lagerdata vesentlig forskjellig fra det som skjedde før. Det er imidlertid ikke mye vanskeligere å legge til mengden av et produkt på lager via produktmodellen enn å legge til 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);

media

Mediestøtte for et produkt for en kunde i en butikk (e-handel) skiller seg som regel fra mediestøtte for samme produkt for en ansatt i et internt regnskapssystem (ERP). I det første tilfellet er det tilrådelig å vise produktet ansikt til ansikt; i det andre er det nok å gi en generell ide om produktet. Det er imidlertid ganske vanlig å overføre i det minste det primære bildet av et produkt. case når du importerer data.

Når du legger til et bilde gjennom administrasjonspanelet, lagres bildet først i en midlertidig katalog (./pub/media/tmp/catalog/product) og kun når du lagrer, flyttes produktet til mediekatalogen (./pub/media/catalog/product). Når det legges til via administrasjonspanelet, blir bildet også merket 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);

Av en eller annen grunn kobles media først etter først å ha lagret produktet og hentet det fra depotet igjen. Og du må spesifisere attributtet label når du legger til en oppføring i produktmediegalleriet (ellers får vi et unntak Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

kategori

Ofte kan kategoristrukturen til butikken og backend-applikasjonen eller plasseringen av produkter i dem variere betydelig. Strategier for å migrere data om kategorier og produkter innenfor dem avhenger av mange faktorer. I dette eksemplet holder jeg meg til følgende:

  • backend- og butikkkategorier sammenlignes etter navn;
  • hvis en kategori importeres som ikke er i butikken, opprettes den under rotkategorien (Default Category) og dens videre plassering i butikkkatalogen antas manuelt;
  • et produkt tildeles en kategori bare når det er opprettet i butikken (første import);

Grunnleggende informasjon om kategorien er i tabellen catalog_category_entity (katalog over kategorier). Opprette en kategori i Magento:

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

Kobling av et produkt til en kategori utføres ved å bruke kategori-ID og produkt-SKU:

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

Totalt

Det er ganske enkelt å skrive kode for å legge til et produkt programmatisk til Magento 2. Jeg har kombinert alt nevnt ovenfor til en demomodul "flancer32/mage2_ext_demo_import". Det er bare én konsollkommando i modulen fl32:import:prod, som importerer produktene beskrevet i JSON-filen "./etc/data/products.json':

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

Bilder for import er i katalogen ./etc/data/img.

Tiden for å importere 10 produkter ved hjelp av denne metoden er omtrent 10 sekunder på min bærbare datamaskin. Hvis vi utvikler denne ideen videre, er det lett å komme til den konklusjonen at ca 3600 produkter kan importeres i timen, og det kan ta ca 100 timer å importere 30K produkter. Ved å bytte ut en bærbar datamaskin med en server kan du jevne ut situasjonen noe. Kanskje til og med flere ganger. Men ikke i størrelsesordener. Kanskje er denne hastigheten og tregheten til en viss grad en av årsakene til prosjektets fremvekst magento/async-import.

En radikal løsning for å øke importhastigheten kan være direkte innføring i databasen, men i dette tilfellet går alle "godbitene" angående utvidbarheten til Magento tapt - du må gjøre alt "avansert" selv. Det er imidlertid verdt det. Hvis det går, vil jeg vurdere tilnærmingen med direkte skriving til databasen i neste artikkel.

Kilde: www.habr.com

Legg til en kommentar