Magento 2: producten importeren uit externe bronnen

Magento is een e-commerceoplossing, d.w.z. is meer gericht op de verkoop van producten dan op warehousing, logistiek of financiële boekhouding bij de verkoop. Andere applicaties (bijvoorbeeld ERP-systemen) zijn beter geschikt voor begeleidende applicaties. Daarom ontstaat in de praktijk van het gebruik van Magento vaak de taak om een ​​winkel te integreren met deze andere systemen (bijvoorbeeld 1C).

Over het algemeen kan integratie worden teruggebracht tot gegevensreplicatie door:

  • catalogus (producten, categorieën);
  • voorraadgegevens (productsaldi in magazijnen en prijzen);
  • klanten;
  • bestellingen;

Magento biedt een aparte klasse objecten voor het manipuleren van gegevens in de database - opslagplaatsen. Vanwege de specifieke kenmerken van Magento is het toevoegen van gegevens aan de database via repositories eenvoudig te coderen, maar het is, laten we zeggen, traag. In deze publicatie bespreek ik de belangrijkste fasen van het programmatisch toevoegen van een product aan Magento 2 op de “klassieke” manier - met behulp van repo-klassen.

Klanten en bestellingen worden meestal in de andere richting gerepliceerd: van Magento naar externe ERP-systemen. Daarom is het eenvoudiger met hen, aan de Magento-kant hoeft u alleen maar de juiste gegevens te selecteren, en dan “kogels vlogen uit onze kant".

Principes van het vastleggen van gegevens in een database

Op dit moment wordt het aanmaken van objecten die programmatisch in Magento in de database zijn opgeslagen, gedaan Fabriek:

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

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

en schrijven naar de database gebeurt via bewaarplaats:

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

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

De ‘Factory’ en ‘Repository’ aanpak kan gebruikt worden voor alle grote modellen in het Magento 2 domein.

Basisproductinformatie

Ik kijk naar een datastructuur die overeenkomt met de Magento 2.3-versie. De meest elementaire informatie over het product vindt u in de tabel catalog_product_entity (productregister):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Ik ben beperkt tot één type product (type_id='simple'), een set standaardkenmerken (attribute_set_id=4) en negeer attributen has_options и required_options. Sinds de attributen entity_id, created_at и updated_at worden automatisch gegenereerd. Om een ​​nieuw product toe te voegen, hoeven we het alleen maar in te stellen sku. Ik doe 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 krijg een uitzondering:

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

Ik voeg de productnaam toe aan het verzoek en krijg de melding dat het attribuut ontbreekt Price. Na het toevoegen van de prijs wordt het product toegevoegd aan de database:

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

De productnaam wordt opgeslagen in de productvarchar-attributentabel (catalog_product_entity_varchar), prijs - in de tabel catalog_product_entity_decimal. Voordat u een product toevoegt, is het raadzaam om expliciet aan te geven dat we de administratieve storefront gebruiken om gegevens te importeren:

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

Aanvullende attributen

Het verwerken van aanvullende productkenmerken met Magento is een plezier. EAV-datamodel voor hoofdentiteiten (zie tabel eav_entity_type) is een van de belangrijkste kenmerken van dit platform. We voegen eenvoudigweg de juiste kenmerken toe aan het productmodel:

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

en bij het opslaan van het model via het repo-object:

$repoProd->save($prod);

aanvullende attributen worden ook opgeslagen in de overeenkomstige databasetabellen.

Voorraadgegevens

In eenvoudige bewoordingen: de hoeveelheid product op voorraad. In Magento 2.3 zijn er structuren in de database die het formaat beschrijven voor het opslaan van inventarisgegevens significant anders van wat er eerder gebeurde. Het toevoegen van de hoeveelheid van een product op voorraad via het productmodel is echter niet veel moeilijker dan het toevoegen van andere 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

Mediaondersteuning voor een product voor een klant in een winkel (e-commerce) verschilt in de regel van mediaondersteuning voor hetzelfde product voor een medewerker in een intern boekhoudsysteem (ERP). In het eerste geval is het raadzaam om het product persoonlijk te laten zien, in het tweede geval is het voldoende om een ​​algemeen idee van het product te geven. Het overbrengen van ten minste de primaire afbeelding van een product is echter heel gebruikelijk. case bij het importeren van gegevens.

Wanneer u een afbeelding toevoegt via het beheerderspaneel, wordt de afbeelding eerst opgeslagen in een tijdelijke map (./pub/media/tmp/catalog/product) en alleen bij het opslaan wordt het product verplaatst naar de mediamap (./pub/media/catalog/product). Wanneer de afbeelding wordt toegevoegd via het beheerdersdashboard, wordt deze ook getagd 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 de een of andere reden worden de media pas gekoppeld nadat het product eerst is opgeslagen en opnieuw uit de repository is opgehaald. En u moet het attribuut specificeren label bij het toevoegen van een item aan de productmediagalerij (anders krijgen we een uitzondering Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

categorie

Vaak kan de categoriestructuur van de winkel en de backend-applicatie of de plaatsing van producten daarin aanzienlijk verschillen. Strategieën voor het migreren van gegevens over categorieën en producten daarin zijn afhankelijk van veel factoren. In dit voorbeeld houd ik het volgende aan:

  • backend- en winkelcategorieën worden op naam vergeleken;
  • als er een categorie wordt geïmporteerd die niet in de winkel staat, wordt deze aangemaakt onder de hoofdcategorie (Default Category) en de verdere positionering ervan in de winkelcatalogus wordt handmatig aangenomen;
  • een product wordt pas aan een categorie toegewezen als het in de winkel wordt aangemaakt (eerste import);

Basisinformatie over de categorie vindt u in de tabel catalog_category_entity (catalogus van categorieën). Een categorie aanmaken in Magento:

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

Het koppelen van een product aan een categorie gebeurt met behulp van de categorie-ID en product-SKU:

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

In totaal

Code schrijven om een ​​product programmatisch toe te voegen aan Magento 2 is vrij eenvoudig. Ik heb alles wat hierboven staat gecombineerd in een demomodule “lancer32/mage2_ext_demo_import". Er is slechts één consoleopdracht in de module fl32:import:prod, die de producten importeert die worden beschreven in het JSON-bestand "./etc/data/products.json":

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

Afbeeldingen voor import staan ​​in de catalogus ./etc/data/img.

De tijd om 10 producten te importeren met deze methode is ongeveer 10 seconden op mijn laptop. Als we dit idee verder uitwerken, kunnen we gemakkelijk tot de conclusie komen dat er ongeveer 3600 producten per uur kunnen worden geïmporteerd, en dat het ongeveer 100 uur kan duren om 30 producten te importeren. Door een laptop te vervangen door een server kunt u de situatie enigszins gladstrijken. Misschien zelfs meerdere keren. Maar niet in ordes van grootte. Misschien is deze snelheid en traagheid tot op zekere hoogte een van de redenen voor het ontstaan ​​van het project magento/async-import.

Een radicale oplossing om de importsnelheid te verhogen zou directe toegang tot de database kunnen zijn, maar in dit geval gaan alle “goodies” met betrekking tot de uitbreidbaarheid van Magento verloren - je zult alles “geavanceerd” zelf moeten doen. Het is echter de moeite waard. Als het lukt, zal ik de aanpak met direct schrijven naar de database in het volgende artikel overwegen.

Bron: www.habr.com

Voeg een reactie