Magento 2: importació de productes de fonts externes

Magento és una solució de comerç electrònic, és a dir. s'adreça més a la venda de productes que a l'emmagatzematge, la logística o la comptabilitat financera que acompanya les vendes. Altres aplicacions (per exemple, sistemes ERP) són més adequades per a les aplicacions acompanyades. Per tant, molt sovint en la pràctica d'utilitzar Magento sorgeix la tasca d'integrar una botiga amb aquests altres sistemes (per exemple, 1C).

En general, la integració es pot reduir a la replicació de dades mitjançant:

  • catàleg (productes, categories);
  • dades d'inventari (saldos de productes en magatzems i preus);
  • clients;
  • comandes;

Magento ofereix una classe separada d'objectes per manipular dades a la base de dades: repositoris. A causa de les especificitats de Magento, afegir dades a la base de dades mitjançant repositoris és fàcil de codificar, però és, diguem-ne, lent. En aquesta publicació, considero les etapes principals d'afegir programàticament un producte a Magento 2 de la manera "clàssica": utilitzant classes de repo.

Els clients i les comandes solen reproduir-se en l'altra direcció: des de Magento fins a sistemes ERP externs. Per tant, amb ells és més senzill, al costat de Magento només cal que seleccioneu les dades adequades i, a continuació, "van sortir bales del nostre costat".

Principis d'enregistrament de dades en una base de dades

De moment, la creació d'objectes desats a la base de dades mitjançant programació a Magento es fa mitjançant Factory:

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

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

i l'escriptura a la base de dades es fa mitjançant Dipòsit:

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

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

L'enfocament "Fàbrica" ​​i "Repositori" es pot utilitzar per a tots els models principals del domini Magento 2.

Informació bàsica del producte

Estic mirant una estructura de dades que coincideix amb la versió 2.3 de Magento. La informació més bàsica sobre el producte es troba a la taula catalog_product_entity (Registre de productes):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

Estic limitat a un tipus de producte (type_id='simple'), un conjunt d'atributs per defecte (attribute_set_id=4) i ignora els atributs has_options и required_options. Des dels atributs entity_id, created_at и updated_at es generen automàticament, llavors, de fet, per afegir un nou producte, només hem de configurar sku. faig això:

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

i tinc una excepció:

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

Afegeixo el nom del producte a la sol·licitud i rebo un missatge que falta l'atribut Price. Després d'afegir el preu, el producte s'afegeix a la base de dades:

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

El nom del producte s'emmagatzema a la taula d'atributs varchar del producte (catalog_product_entity_varchar), preu - a la taula catalog_product_entity_decimal. Abans d'afegir un producte, és recomanable indicar explícitament que estem utilitzant l'aparador administratiu per importar dades:

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

Atributs addicionals

Processar atributs addicionals de producte amb Magento és un plaer. Model de dades EAV per a les entitats principals (vegeu taula eav_entity_type) és una de les característiques clau d'aquesta plataforma. Simplement afegim els atributs adequats al model de producte:

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

i quan deseu el model mitjançant l'objecte de repo:

$repoProd->save($prod);

els atributs addicionals també s'emmagatzemaran a les taules de bases de dades corresponents.

Dades d'inventari

En termes simples: la quantitat de producte en estoc. A Magento 2.3, les estructures de la base de dades que descriuen el format per emmagatzemar les dades d'inventari són significativament diferents del que va passar abans. Tanmateix, afegir la quantitat d'un producte en estoc mitjançant el model de producte no és molt més difícil que afegir altres atributs:

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

Mitjans de comunicació

Per regla general, el suport de mitjans per a un producte per a un client en una botiga (comerç electrònic) difereix del suport de mitjans per al mateix producte per a un empleat en un sistema de comptabilitat intern (ERP). En el primer cas, s'aconsella mostrar el producte cara a cara; en el segon, n'hi ha prou amb donar una idea general del producte. Tanmateix, transferir almenys la imatge principal d'un producte és força habitual. case en importar dades.

Quan s'afegeix una imatge a través del tauler d'administració, la imatge es desa primer en un directori temporal (./pub/media/tmp/catalog/product) i només quan es desa el producte es mou al directori multimèdia (./pub/media/catalog/product). A més, quan s'afegeix mitjançant el tauler d'administració, la imatge s'etiqueta 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);

Per algun motiu, el suport només s'enllaça després de desar el producte i recuperar-lo de nou del dipòsit. I heu d'especificar l'atribut label en afegir una entrada a la galeria multimèdia del producte (en cas contrari, obtenim una excepció Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

Категории

Sovint, l'estructura de categories de la botiga i l'aplicació de fons o la col·locació dels productes en elles poden diferir significativament. Les estratègies per migrar dades sobre categories i productes dins d'elles depenen de molts factors. En aquest exemple em quedo amb el següent:

  • Les categories de backend i botiga es comparen pel nom;
  • si s'importa una categoria que no es troba a la botiga, es crea sota la categoria arrel (Default Category) i el seu posterior posicionament al catàleg de la botiga s'assumeix manualment;
  • un producte s'assigna a una categoria només quan es crea a la botiga (primera importació);

La informació bàsica sobre la categoria es troba a la taula catalog_category_entity (catàleg de categories). Creació d'una categoria a Magento:

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

L'enllaç d'un producte a una categoria es realitza mitjançant l'identificador de categoria i el SKU del producte:

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

En total

Escriure codi per afegir un producte amb programació a Magento 2 és bastant fàcil. He combinat tot el que s'ha dit anteriorment en un mòdul de demostració "flancer32/mage2_ext_demo_import". Només hi ha una comanda de consola al mòdul fl32:import:prod, que importa els productes descrits al fitxer JSON "./etc/data/products.json":

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

Les imatges per a la importació estan al catàleg ./etc/data/img.

El temps per importar 10 productes amb aquest mètode és d'uns 10 segons al meu ordinador portàtil. Si desenvolupem aquesta idea més, és fàcil arribar a la conclusió que es poden importar uns 3600 productes per hora i que es poden trigar unes 100 hores a importar 30 productes. Substituir un ordinador portàtil per un servidor us permet suavitzar una mica la situació. Potser fins i tot diverses vegades. Però no per ordres de magnitud. Potser aquesta velocitat i lentitud és fins a cert punt un dels motius de l'aparició del projecte magento/async-import.

Una solució radical per augmentar la velocitat d'importació podria ser l'entrada directa a la base de dades, però en aquest cas es perden tots els "bons" pel que fa a l'extensibilitat de Magento: ho haureu de fer tot "avançat". No obstant això, val la pena. Si funciona, consideraré l'enfocament amb l'escriptura directa a la base de dades al següent article.

Font: www.habr.com

Afegeix comentari