Magento 2: import af produkter fra eksterne kilder

Magento er en e-handel løsning, der er mere fokuseret på salg af produkter end på tilknyttede salg som lager, logistik eller finansiel bogføring. Til det sidstnævnte er andre applikationer (som ERP-systemer) bedre egnet. Derfor opstår der i praksis ofte en opgave med at integrere butikken med disse andre systemer (f.eks. med 1C).

I store træk kan integrationen reduceres til replikering af data på:

  • kataloget (produkter, kategorier);
  • lagerdata (produktmængder på lagre og priser);
  • kunder;
  • ordrer;

Magento tilbyder en separat klasse objekter til manipulation af data i databasen — repository. På grund af Magento's specifikationer er det let at kode tilføjelse af data til databasen gennem repository'er, men det sker, lad os sige, ikke hurtigt. I denne publikation gennemgår jeg de grundlæggende trin for programmeringsmæssig tilføjelse af et produkt til Magento 2 på den "klassiske" måde — ved at bruge repo-klasser.

Kunder og ordrer replikeres normalt i den modsatte retning — fra Magento til eksterne ERP-systemer. Derfor er det enklere, på Magento-siden skal man blot vælge de relevante data, og så — "fra vores side er kuglerne skudt«.

Principper for indskrivning af data i databasen

I øjeblikket sker oprettelsen af objekter, der gemmes i databasen, programmatisk i Magento gennem Factory:

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

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

og indskrivningen i databasen — gennem Repository:

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

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

Tilgangen med at bruge "Factory" og "Repository" kan anvendes til alle grundlæggende modeller inden for Magento 2's emneområde.

Grundlæggende information om produktet

Jeg gennemgår datastukturen, der svarer til versionen Magento 2.3. Den mest grundlæggende information om produktet findes i tabellen catalog_product_entity (produktregister):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Jeg begrænser mig til én produkttype (type_id='simple'), et sæt attributter som standard (attribute_set_id=4) og ignorerer attributterne has_options og required_options. Da attributterne entity_id, created_at og updated_at genereres automatisk, er det i princippet nok for os at angive sku. Jeg gør det på følgende måde:

/** @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 får en undtagelse:

Attributværdien for "Produktnavn" er tom. Indstil attributten og prøv igen.

Jeg tilføjer produktnavnet i forespørgslen og får besked om, at der mangler et attribut. Pris. Efter tilføjelse af prisen bliver produktet gemt i 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 tabellen for varchar-attributter (katalog_product_entity_varchar), prisen gemmes i tabellen catalog_product_entity_decimal. Før tilføjelsen af produktet er det en god idé at angive eksplicit, at vi bruger administrationsgrænsefladen til at importere data:

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

Yderligere attributter

Behandlingen af yderligere produktattributter med Magento er en fornøjelse. EAV-datamodellen for de primære entiteter (se tabel eav_entity_type) er en af de centrale funktioner ved denne platform. Vi tilføjer ganske enkelt de relevante attributter til produktmodellen:

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

og når modellen gemmes gennem repo-objektet:

$repoProd->save($prod);

vil de yderligere attributter også blive gemt i de relevante databaser.

Inventory data

Simpelt sagt — produktantal på lager. I Magento 2.3 er strukturerne i databasen, der beskriver formatet for opbevaring af inventardata, betydeligt forskellige fra hvad der var tidligere. Ikke desto mindre er tilføjelsen af produktantal på lager gennem produktmodellen ikke meget mere kompliceret end tilføjelsen af 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

Generelt adskiller mediesupport til produktet for kunden i butikken (e-commerce) sig fra mediesupport til det samme produkt for medarbejderen i det interne regnskabssystem (ERP). I det første tilfælde er det ønskeligt at vise "varen ansigt til ansigt", i det andet tilfælde er det nok at give et overordnet indtryk af produktet. Ikke desto mindre er overførslen af selv det primære billede af produktet en ret almindelig case ved dataimport.

Når et billede tilføjes via adminpanelet, gemmes billedet først i en midlertidig mappe (./pub/media/tmp/catalog/product) og flyttes først til mediemappen (./pub/media/catalog/product) ved gemmelsen af produktet. Desuden tildeles billedet i adminpanelet tags. billede, 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 tilknyttes mediet kun efter en forudgående gemmelse af produktet og efterfølgende hentning af det fra repository igen. Der skal angives et attribut label ved tilføjelse af posten i produktets mediagalleri (ellers får vi en undtagelse Udefineret indeks: label i .../module-catalog/Model/Product/Gallery/CreateHandler.php på linje 516).

Kategorier

Strukturen af kategoriwebshoppen og backend-applikationen eller placeringen af produkter i dem kan ofte variere betydeligt. Strategierne for overførsel af data om kategorier og produkter i dem afhænger af mange faktorer. I dette eksempel følger jeg følgende:

  • backend-kategorierne og butikken matches efter navn;
  • hvis en kategori importeres, som ikke findes i butikken, oprettes den under rodkategorien (Default Category) og dens fremtidige placering i butikskataloget skal antages at ske manuelt;
  • bindingen af produktet til kategorien sker kun ved oprettelsen i butikken (første import);

Den primære information om kategorien findes i tabellen catalog_category_entity (kategori katalog). Oprettelse af kategori i Magento:

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

Bindingen af produktet til kategorien sker via kategoriens ID og produktets SKU:

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

I alt

At skrive koden for at tilføje et produkt til Magento 2 programmatisk er ret enkelt. Alt hvad jeg har beskrevet ovenfor har jeg samlet i demomodulet "flancer32/mage2_ext_demo_import". Modulens eneste konsolkommando er fl32:import:prod, som importerer produkter beskrevet i JSON-filen "./etc/data/products.json«:

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

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

Tiden for import af 10 produkter på denne måde tager cirka 10 sekunder på min bærbare computer. Hvis man arbejder videre med denne tanke, er det ikke svært at konkludere, at man kan importere cirka 3600 produkter i timen, og importen af 100K produkter kan tage omkring 30 timer. At erstatte den bærbare computer med en server kan i høj grad forbedre situationen. Det kan endda være flere gange bedre. Men ikke i rækkefølge. Måske er denne langsomhed i et vist omfang en af årsagerne til fremkomsten af projektet magento/async-import.

En radikal løsning for at øge hastigheden af importen kan være direkte skrivning til databasen, men i så fald mistes alle "fordele" vedrørende udvideligheden af Magento – man må selv gøre alt det "udvidede". Ikke desto mindre er det det værd. Hvis det lykkes, vil jeg overveje tilgangen med direkte skrivning til BDan i næste artikel.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster