Magento 2: produkten ymportearje fan eksterne boarnen

Magento is in e-commerce oplossing, d.w.s. is mear rjochte op it ferkeapjen fan produkten as op de byhearrende ferkeap opslach, logistyk of finansjele boekhâlding. Oare applikaasjes (bygelyks ERP-systemen) binne better geskikt foar begeliedende applikaasjes. Dêrom, yn 'e praktyk fan it brûken fan Magento, ûntstiet de taak om in winkel te yntegrearjen mei dizze oare systemen (bygelyks 1C).

Yn 't algemien kin yntegraasje wurde fermindere ta gegevensreplikaasje troch:

  • katalogus (produkten, kategoryen);
  • ynventarisgegevens (produktbalansen yn pakhuzen en prizen);
  • kliïnten;
  • oarders;

Magento biedt in aparte klasse fan objekten foar it manipulearjen fan gegevens yn 'e databank - repositories. Troch de spesifikaasjes fan Magento is it tafoegjen fan gegevens oan 'e databank fia repositories maklik te koade, mar it is, litte wy sizze, stadich. Yn dizze publikaasje beskôgje ik de wichtichste stadia fan programmatysk tafoegjen fan in produkt oan Magento 2 op 'e "klassike" manier - mei help fan repo-klassen.

Klanten en oarders wurde normaal replikearre yn 'e oare rjochting - fan Magento oant eksterne ERP-systemen. Dêrom is it makliker mei har, oan 'e Magento-kant moatte jo gewoan de passende gegevens selektearje, en dan "kûgels fleagen út ús kant".

Prinsipes fan it opnimmen fan gegevens yn in databank

Op it stuit wurdt it meitsjen fan objekten opslein yn 'e databank programmatysk yn Magento dien troch fabryk:

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

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

en it skriuwen nei de databank wurdt dien troch Repository:

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

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

De "Factory" en "Repository" oanpak kin brûkt wurde foar alle grutte modellen yn it Magento 2-domein.

Basis produkt ynformaasje

Ik sjoch nei in gegevensstruktuer dy't oerienkomt mei Magento 2.3 ferzje. De meast basale ynformaasje oer it produkt is yn 'e tabel catalog_product_entity (produktregister):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Ik bin beheind ta ien type produkt (type_id='simple'), in set fan standert attributen (attribute_set_id=4) en negearje attributen has_options и required_options. Sûnt de attributen entity_id, created_at и updated_at wurde automatysk oanmakke, dan, yn feite, om in nij produkt ta te foegjen, moatte wy gewoan ynstelle sku. Ik doch dit:

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

en ik krij in útsûndering:

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

Ik foegje de produktnamme ta oan it fersyk en krij in berjocht dat it attribút ûntbrekt Price. Nei it tafoegjen fan de priis wurdt it produkt tafoege oan de databank:

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

De produktnamme wurdt opslein yn 'e produkt varchar attribút tabel (catalog_product_entity_varchar), priis - yn 'e tabel catalog_product_entity_decimal. Foardat jo in produkt tafoegje, is it oan te rieden om eksplisyt oan te jaan dat wy it bestjoerlike winkelfront brûke om gegevens te ymportearjen:

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

Oanfoljende attributen

It ferwurkjen fan ekstra produktattributen mei Magento is in genot. EAV-gegevensmodel foar haadentiteiten (sjoch tabel eav_entity_type) is ien fan 'e wichtichste funksjes fan dit platfoarm. Wy foegje gewoan de passende attributen ta oan it produktmodel:

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

en by it bewarjen fan it model fia it repo-objekt:

$repoProd->save($prod);

ekstra attributen sille ek wurde opslein yn de byhearrende databank tabellen.

Ynventarisaasje gegevens

Yn ienfâldige termen - it bedrach fan it produkt op foarried. Yn Magento 2.3 binne struktueren yn 'e databank dy't it formaat beskriuwe foar it bewarjen fan ynventarisgegevens signifikant oars fan wat der earder bard is. It tafoegjen fan de kwantiteit fan in produkt op foarried fia it produktmodel is lykwols net folle dreger dan it tafoegjen fan oare attributen:

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

Media

Yn 'e regel ferskilt mediastipe foar in produkt foar in klant yn in winkel (e-commerce) fan mediastipe foar itselde produkt foar in meiwurker yn in ynterne boekhâldingsysteem (ERP). Yn it earste gefal is it oan te rieden om it produkt oantlit ta oantlit te sjen; yn it twadde is it genôch om in algemien idee fan it produkt te jaan. It oerdragen fan op syn minst de primêre ôfbylding fan in produkt is lykwols frij gewoan. case by it ymportearjen fan gegevens.

By it tafoegjen fan in ôfbylding fia it adminpaniel, wurdt de ôfbylding earst bewarre yn in tydlike map (./pub/media/tmp/catalog/product) en allinich by it bewarjen fan it produkt wurdt ferpleatst nei de mediamap (./pub/media/catalog/product). Ek, as tafoege fia it adminpaniel, wurdt de ôfbylding tagged 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);

Om ien of oare reden is de media allinich keppele nei it earst opslaan fan it produkt en it wer opheljen fan it repository. En jo moatte it attribút opjaan label by it tafoegjen fan in yngong oan 'e produktmediagalery (oars krije wy in útsûndering Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

Categories

Faak kinne de kategorystruktuer fan 'e winkel en de backend-applikaasje as de pleatsing fan produkten dêryn signifikant ferskille. Strategyen foar it migrearjen fan gegevens oer kategoryen en produkten binnen har binne ôfhinklik fan in protte faktoaren. Yn dit foarbyld hâlde ik my oan it folgjende:

  • backend- en winkelkategoryen wurde fergelike mei namme;
  • as in kategory wurdt ymportearre dy't net yn 'e winkel is, dan wurdt it makke ûnder de rootkategory (Default Category) en de fierdere posisjonearring dêrfan yn 'e winkelkatalogus wurdt manuell oannommen;
  • in produkt wurdt allinich oan in kategory tawiisd as it yn 'e winkel makke is (earste ymport);

Basisynformaasje oer de kategory is yn 'e tabel catalog_category_entity (katalogus fan kategoryen). In kategory oanmeitsje yn Magento:

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

It keppeljen fan in produkt oan in kategory wurdt útfierd mei de kategory ID en produkt SKU:

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

Totaal

Koade skriuwe om in produkt programmatysk ta te foegjen oan Magento 2 is frij maklik. Ik haw alles hjirboppe kombinearre yn in demomodule "flancer32/mage2_ext_demo_import". D'r is mar ien konsolekommando yn 'e module fl32:import:prod, dy't de produkten ymportearret beskreaun yn it JSON-bestân "./etc/data/products.json":

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

Ofbyldings foar ymport binne yn 'e katalogus ./etc/data/img.

De tiid om 10 produkten te ymportearjen mei dizze metoade is sawat 10 sekonden op myn laptop. As wy ûntwikkelje dit idee fierder, is it maklik om te kommen ta de konklúzje dat oer 3600 produkten kinne wurde ymportearre per oere, en it kin nimme oer 100 oeren in ymportearje 30K produkten. It ferfangen fan in laptop mei in server lit jo de situaasje wat glêd meitsje. Miskien sels ferskate kearen. Mar net troch oarders fan grutte. Faaks is dizze snelheid en traagheid foar in part ien fan 'e redenen foar it ûntstean fan it projekt magento/async-ymport.

In radikale oplossing om de snelheid fan ymport te ferheegjen kin direkte tagong wêze yn 'e databank, mar yn dit gefal binne alle "guod" oangeande de útwreidzjen fan Magento ferlern - jo moatte alles "avansearre" sels dwaan. Lykwols, it is it wurdich. As it slagget, sil ik yn it folgjende artikel de oanpak mei direkt skriuwen nei de databank beskôgje.

Boarne: www.habr.com

Add a comment