Magento 2: Pag-import ng Mga Produkto mula sa Mga Panlabas na Pinagmumulan

Ang Magento ay isang solusyon sa e-commerce, ibig sabihin. ay mas naglalayong magbenta ng mga produkto kaysa sa warehousing, logistik o financial accounting na kasama ng mga benta. Ang iba pang mga application (halimbawa, mga ERP system) ay mas angkop para sa mga kasamang application. Samakatuwid, medyo madalas sa pagsasanay ng paggamit ng Magento ang gawain ng pagsasama ng isang tindahan sa iba pang mga system na ito (halimbawa, 1C) ay lumitaw.

Sa pangkalahatan, ang pagsasama ay maaaring bawasan sa pagkopya ng data sa pamamagitan ng:

  • katalogo (mga produkto, kategorya);
  • data ng imbentaryo (mga balanse ng produkto sa mga bodega at presyo);
  • mga kliyente;
  • mga order;

Nag-aalok ang Magento ng isang hiwalay na klase ng mga bagay para sa pagmamanipula ng data sa database - mga repositoryo. Dahil sa mga detalye ng Magento, ang pagdaragdag ng data sa database sa pamamagitan ng mga repository ay madaling i-code, ngunit ito ay, sabihin nating, mabagal. Sa publication na ito, isinasaalang-alang ko ang mga pangunahing yugto ng programmatically pagdaragdag ng isang produkto sa Magento 2 sa "classic" na paraan - gamit ang mga repo class.

Ang mga customer at order ay karaniwang ginagaya sa kabilang direksyon - mula Magento hanggang sa mga panlabas na ERP system. Samakatuwid, ito ay mas simple sa kanila, sa gilid ng Magento kailangan mo lamang piliin ang naaangkop na data, at pagkatapos ay "nagliparan ang mga bala mula sa gilid namin".

Mga prinsipyo ng pagtatala ng data sa isang database

Sa ngayon, ginagawa ang paglikha ng mga bagay na naka-save sa database gamit ang programmatically sa Magento Pabrika:

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

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

at ang pagsulat sa database ay ginagawa sa pamamagitan ng Repository:

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

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

Ang diskarte na "Factory" at "Repository" ay maaaring gamitin para sa lahat ng pangunahing modelo sa domain ng Magento 2.

Pangunahing Impormasyon ng Produkto

Tinitingnan ko ang isang istraktura ng data na tumutugma sa bersyon ng Magento 2.3. Ang pinakapangunahing impormasyon tungkol sa produkto ay nasa talahanayan catalog_product_entity (pagpapatala ng produkto):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Limitado ako sa isang uri ng produkto (type_id='simple'), isang hanay ng mga default na katangian (attribute_set_id=4) at huwag pansinin ang mga katangian has_options ΠΈ required_options. Dahil ang mga katangian entity_id, created_at ΠΈ updated_at ay awtomatikong nabuo, pagkatapos, sa katunayan, upang magdagdag ng isang bagong produkto, kailangan lang nating itakda sku. Ginagawa ko ito:

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

at nakakakuha ako ng exception:

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

Idinaragdag ko ang pangalan ng produkto sa kahilingan at nakakuha ako ng mensahe na nawawala ang attribute Price. Pagkatapos idagdag ang presyo, idinagdag ang produkto sa database:

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

Ang pangalan ng produkto ay naka-imbak sa product varchar attribute table (catalog_product_entity_varchar), presyo - sa talahanayan catalog_product_entity_decimal. Bago magdagdag ng produkto, ipinapayong tahasang isaad na ginagamit namin ang administratibong storefront upang mag-import ng data:

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

Mga Karagdagang Katangian

Ang pagproseso ng mga karagdagang katangian ng produkto gamit ang Magento ay isang kasiyahan. Modelo ng data ng EAV para sa mga pangunahing entity (tingnan ang talahanayan eav_entity_type) ay isa sa mga pangunahing tampok ng platform na ito. Idinaragdag lang namin ang mga naaangkop na katangian sa modelo ng produkto:

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

at kapag nagse-save ng modelo sa pamamagitan ng repo object:

$repoProd->save($prod);

Ang mga karagdagang katangian ay maiimbak din sa kaukulang mga talahanayan ng database.

Data ng imbentaryo

Sa madaling salita - ang dami ng produkto sa stock. Sa Magento 2.3, ang mga istruktura sa database na naglalarawan sa format para sa pag-iimbak ng data ng imbentaryo ay makabuluhang naiiba mula sa nangyari kanina. Gayunpaman, ang pagdaragdag ng dami ng isang produkto sa stock sa pamamagitan ng modelo ng produkto ay hindi mas mahirap kaysa sa pagdaragdag ng iba pang mga katangian:

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

Media

Bilang isang patakaran, ang suporta ng media para sa isang produkto para sa isang kliyente sa isang tindahan (e-commerce) ay naiiba sa suporta ng media para sa parehong produkto para sa isang empleyado sa isang internal accounting system (ERP). Sa unang kaso, ipinapayong ipakita ang produkto nang harapan; sa pangalawa, sapat na upang magbigay ng pangkalahatang ideya ng produkto. Gayunpaman, ang paglilipat ng hindi bababa sa pangunahing larawan ng isang produkto ay karaniwan. case kapag nag-import ng data.

Kapag nagdadagdag ng larawan sa pamamagitan ng admin panel, ang larawan ay unang nai-save sa isang pansamantalang direktoryo (./pub/media/tmp/catalog/product) at kapag ang pag-save ng produkto ay inilipat sa direktoryo ng media (./pub/media/catalog/product). Gayundin, kapag idinagdag sa pamamagitan ng admin panel, ang larawan ay na-tag 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);

Para sa ilang kadahilanan, ang media ay naka-link lamang pagkatapos munang i-save ang produkto at makuha itong muli mula sa repository. At kailangan mong tukuyin ang katangian label kapag nagdadagdag ng entry sa gallery ng media ng produkto (kung hindi, makakakuha tayo ng exception Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

Kategorya

Kadalasan, ang istraktura ng kategorya ng tindahan at ang backend na application o ang paglalagay ng mga produkto sa mga ito ay maaaring mag-iba nang malaki. Ang mga diskarte para sa paglilipat ng data tungkol sa mga kategorya at produkto sa loob ng mga ito ay nakadepende sa maraming salik. Sa halimbawang ito nananatili ako sa sumusunod:

  • inihahambing ang mga kategorya ng backend at store ayon sa pangalan;
  • kung ang isang kategorya ay na-import na wala sa tindahan, pagkatapos ito ay nilikha sa ilalim ng root na kategorya (Default Category) at ang karagdagang pagpoposisyon nito sa katalogo ng tindahan ay ipinapalagay nang manu-mano;
  • ang isang produkto ay itinalaga sa isang kategorya lamang kapag ito ay ginawa sa tindahan (unang pag-import);

Ang pangunahing impormasyon tungkol sa kategorya ay nasa talahanayan catalog_category_entity (catalog ng mga kategorya). Paglikha ng kategorya sa Magento:

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

Ang pag-link ng produkto sa isang kategorya ay isinasagawa gamit ang category ID at SKU ng produkto:

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

Sa kabuuan

Ang pagsulat ng code upang magdagdag ng isang produkto sa programmatically sa Magento 2 ay medyo madali. Pinagsama ko ang lahat ng nakasaad sa itaas sa isang demo module "flancer32/mage2_ext_demo_import". Mayroon lamang isang console command sa module fl32:import:prod, na nag-i-import ng mga produktong inilarawan sa JSON file "./etc/data/products.json":

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

Ang mga larawan para sa pag-import ay nasa catalog ./etc/data/img.

Ang oras para mag-import ng 10 produkto gamit ang paraang ito ay mga 10 segundo sa aking laptop. Kung bubuo pa natin ang ideyang ito, madaling magkaroon ng konklusyon na humigit-kumulang 3600 produkto ang maaaring ma-import bawat oras, at maaaring tumagal ng humigit-kumulang 100 oras upang mag-import ng 30K na produkto. Ang pagpapalit ng isang laptop ng isang server ay nagbibigay-daan sa iyo upang maayos ang sitwasyon. Siguro kahit ilang beses. Ngunit hindi sa pamamagitan ng mga order ng magnitude. Marahil ang bilis at kabagalan na ito ay sa ilang lawak ang isa sa mga dahilan ng paglitaw ng proyekto magento/async-import.

Ang isang radikal na solusyon upang madagdagan ang bilis ng pag-import ay maaaring direktang pagpasok sa database, ngunit sa kasong ito ang lahat ng "goodies" tungkol sa pagpapalawak ng Magento ay nawala - kailangan mong gawin ang lahat ng "advanced" sa iyong sarili. Gayunpaman, sulit ito. Kung ito ay gagana, isasaalang-alang ko ang diskarte sa direktang pagsulat sa database sa susunod na artikulo.

Pinagmulan: www.habr.com

Magdagdag ng komento