Magento 2: Importera produkter från externa källor

Magento är en e-handelslösning, d.v.s. är mer inriktat på att sälja produkter än på lager, logistik eller finansiell redovisning i samband med försäljning. Andra applikationer (exempelvis affärssystem) är bättre lämpade för medföljande applikationer. Därför uppstår ganska ofta i praktiken att använda Magento uppgiften att integrera en butik med dessa andra system (till exempel 1C).

I stort sett kan integration reduceras till datareplikering genom att:

  • katalog (produkter, kategorier);
  • lagerdata (produktbalanser i lager och priser);
  • kunder;
  • order;

Magento erbjuder en separat klass av objekt för att manipulera data i databasen - förråd. På grund av Magentos särdrag är det lätt att lägga till data till databasen genom förråd, men det är, låt oss säga, långsamt. I den här publikationen överväger jag huvudstadierna av att programmatiskt lägga till en produkt till Magento 2 på det "klassiska" sättet - med hjälp av repoklasser.

Kunder och beställningar replikeras vanligtvis åt andra hållet – från Magento till externa affärssystem. Därför är det enklare med dem, på Magento-sidan behöver du bara välja lämplig data och sedan "kulor flög ut från vår sida".

Principer för att registrera data i en databas

För tillfället går det att skapa objekt som sparats i databasen programmatiskt i Magento Fabrik:

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

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

och skrivning till databasen görs igenom förvaret:

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

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

Tillvägagångssätten "Factory" och "Repository" kan användas för alla större modeller i Magento 2-domänen.

Grundläggande produktinformation

Jag tittar på en datastruktur som matchar Magento 2.3-versionen. Den mest grundläggande informationen om produkten finns i tabellen catalog_product_entity (produktregister):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Jag är begränsad till en typ av produkt (type_id='simple'), en uppsättning standardattribut (attribute_set_id=4) och ignorera attribut has_options и required_options. Eftersom attributen entity_id, created_at и updated_at genereras automatiskt, då, i själva verket, för att lägga till en ny produkt behöver vi bara ställa in sku. Jag gör detta:

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

och jag får ett undantag:

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

Jag lägger till produktnamnet i förfrågan och får ett meddelande om att attributet saknas Price. Efter att ha lagt till priset läggs produkten till i databasen:

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

Produktnamnet lagras i produktens varchar-attributtabell (catalog_product_entity_varchar), pris - i tabellen catalog_product_entity_decimal. Innan du lägger till en produkt är det lämpligt att uttryckligen ange att vi använder det administrativa skyltfönstret för att importera data:

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

Ytterligare attribut

Att bearbeta ytterligare produktattribut med Magento är ett nöje. EAV-datamodell för huvudenheter (se tabell eav_entity_type) är en av nyckelfunktionerna i denna plattform. Vi lägger helt enkelt till lämpliga attribut till produktmodellen:

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

och när du sparar modellen via repo-objektet:

$repoProd->save($prod);

ytterligare attribut kommer också att lagras i motsvarande databastabeller.

Inventeringsdata

Enkelt uttryckt - mängden produkt i lager. I Magento 2.3 finns strukturer i databasen som beskriver formatet för lagring av lagerdata väsentligt olika från det som hände innan. Att lägga till mängden av en produkt i lager via produktmodellen är dock inte mycket svårare än att lägga till andra attribut:

/** @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öd för en produkt för en kund i en butik (e-handel) skiljer sig som regel från mediestöd för samma produkt för en anställd i ett internt ekonomisystem (ERP). I det första fallet är det lämpligt att visa produkten ansikte mot ansikte; i det andra räcker det för att ge en allmän uppfattning om produkten. Det är dock ganska vanligt att överföra åtminstone den primära bilden av en produkt. case vid import av data.

När du lägger till en bild via adminpanelen sparas bilden först i en tillfällig katalog (./pub/media/tmp/catalog/product) och endast när du sparar flyttas produkten till mediakatalogen (./pub/media/catalog/product). När bilden läggs till via adminpanelen är bilden också taggad 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 någon anledning länkas media först efter att man först har sparat produkten och hämtat den från förvaret igen. Och du måste ange attributet label när du lägger till en post i produktens mediagalleri (annars får vi ett undantag Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

kategori

Ofta kan kategoristrukturen för butiken och backend-applikationen eller placeringen av produkter i dem skilja sig avsevärt. Strategier för att migrera data om kategorier och produkter inom dem beror på många faktorer. I detta exempel håller jag mig till följande:

  • backend- och butikskategorier jämförs med namn;
  • om en kategori importeras som inte finns i butiken skapas den under rotkategorin (Default Category) och dess vidare positionering i butikskatalogen antas manuellt;
  • en produkt tilldelas en kategori först när den skapas i butiken (första importen);

Grundläggande information om kategorin finns i tabellen catalog_category_entity (katalog över kategorier). Skapa en kategori i Magento:

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

Att länka en produkt till en kategori görs med hjälp av kategori-ID och produkt-SKU:

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

Totalt

Att skriva kod för att lägga till en produkt programmatiskt till Magento 2 är ganska enkelt. Jag har kombinerat allt som anges ovan till en demomodul "flancer32/mage2_ext_demo_import". Det finns bara ett konsolkommando i modulen fl32:import:prod, som importerar produkterna som beskrivs i JSON-filen "./etc/data/products.json':

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

Bilder för import finns i katalogen ./etc/data/img.

Tiden för att importera 10 produkter med den här metoden är cirka 10 sekunder på min bärbara dator. Om vi ​​utvecklar denna idé vidare är det lätt att komma fram till att cirka 3600 produkter kan importeras per timme, och det kan ta cirka 100 timmar att importera 30K produkter. Genom att byta ut en bärbar dator mot en server kan du jämna ut situationen något. Kanske till och med flera gånger. Men inte i storleksordningar. Kanske är denna hastighet och långsamhet i viss mån en av anledningarna till projektets uppkomst magento/async-import.

En radikal lösning för att öka importhastigheten kan vara direkt inträde i databasen, men i det här fallet går alla "godsaker" angående Magentos utökbarhet förlorade - du måste göra allt "avancerat" själv. Det är dock värt det. Om det löser sig kommer jag att överväga tillvägagångssättet med direktskrivning till databasen i nästa artikel.

Källa: will.com

Lägg en kommentar