Magento е решение за електронна търговия, т.е. по-скоро е насочено към продажба на продукти, отколкото към свързаните с продажбите складови, логистични или финансови записи. За тези цели по-подходящи са други приложения (например, ERP системи). Затова често в практиката на работа с Magento възниква нужда от интегриране на магазина с тези други системи (например, с 1С).
По принцип интеграцията може да се сведе до репликиране на данни по:
- каталога (продукти, категории);
- инвентарни данни (остатъци от продукти на складовете и цени);
- клиентите;
- поръчките;
Magento предлага отделен клас обекти за манипулиране с данни в базата — . Поради спецификата на Magento, добавянето на данни в базата чрез репозиториите лесно се кодира, но става, да кажем, не толкова бързо. В тази публикация разглеждам основните етапи на програмното добавяне на продукт в Magento 2 по "класически" начин — с използване на репо класове.
Клиентите и поръчките обикновено се репликират в друга посока — от Magento към външни ERP системи. Така че с тях е по-просто, на страната на Magento е нужно просто да се изберат съответните данни, а след това — "от наша страна куршумите излетяха«.
Принципи на запис на данни в базата
Към момента, създаването на обекти, които се съхраняват в базата, по програмен начин в Magento се прави чрез :
function __construct (MagentoCmsModelBlockFactory $blockFactory) {
$this->blockFactory = $blockFactory;
}
/** @var MagentoCmsModelBlock $block * */
$block = $this->blockFactory->create();а записът в базата — чрез :
function __construct (MagentoCmsApiBlockRepositoryInterface $blockRepo) {
$this->blockRepo = $blockRepo;
}
$this->blockRepo->save($block);Подходът с използване на "Factory" и "Repository" може да се приложи за всички основни модели в предметната област на Magento 2.
Основна информация за продукта
Разглеждам структурата на данните, съответстваща на версията Magento 2.3. Най-основната информация за продукта се намира в таблицата catalog_product_entity (регистър на продуктите):
entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_atОграничавам се до един тип продукт (type_id='simple'), набор атрибути по подразбиране (attribute_set_id=4) и игнорирам атрибутите has_options и required_options. Тъй като атрибутите entity_id, created_at и updated_at се генерират автоматично, то всъщност, за добавяне на нов продукт, ни е достатъчно да зададем sku. Правя така:
/** @var MagentoCatalogApiDataProductInterfaceFactory $factProd */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
/** @var MagentoCatalogApiDataProductInterface $prod */
$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$repoProd->save($prod);и получавам изключение:
Атрибутът "Product Name" е празен. Задайте стойност за атрибута и опитайте отново.Добавям към заявката името на продукта и получавам съобщение, че липсва атрибут. Цена. След добавяне на цената, продуктът се записва в базата:
$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$prod->setName($name);
$prod->setPrice($price);
$repoProd->save($prod);Името на продукта се записва в таблицата varchar-атрибути на продукта (catalog_product_entity_varchar), цената — в таблицата catalog_product_entity_decimal. Преди добавяне на продукта, е желателно явно да се уточни, че използваме административен интерфейс за импортиране на данни:
/** @var MagentoStoreModelStoreManagerInterface $manStore */
$manStore->setCurrentStore(0);Допълнителни атрибути
Обработката на допълнителни атрибути на продуктите с помощта на Magento е истинско удоволствие. EAV-моделът на данни за основните сущности (виж таблицата eav_entity_type) е една от ключовите характеристики на тази платформа. Просто добавяме съответните атрибути към модела на продукта:
$prodEntity->setData('description', $desc);
$prodEntity->setData('short_description', $desc_short);
// или
$prodEntity->setDescription($desc);
$prodEntity->setShortDescription($desc_short);и при записването на модела чрез репо-обект:
$repoProd->save($prod);допълнителните атрибути също ще бъдат записани в съответните таблици на базата данни.
Данни за инвентара
Просто казано — количеството на продукта на склад. В Magento 2.3 структурите в базата данни, описващи формата на съхранение на инвентарни данни, от предишните версии. Въпреки това, добавянето на количество на продукта на склад чрез модела на продукта не е много по-сложно от добавянето на други атрибути:
/** @var MagentoCatalogModelProduct $prodEntity */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
$inventory = [
'is_in_stock' => true,
'qty' => 1234
];
$prodEntity->setData('quantity_and_stock_status', $inventory);
$repoProd->save($prodEntity);Медия
Като правило, медийната придружаване на продукта за клиента в магазина (e-commerce) се различава от медийната придружаване на същия продукт за служителя в външната система за отчитане (ERP). В първия случай е желателно да се покаже 'товар лицом', а във втория — е достатъчно да се даде общо представяне на продукта. Въпреки това, прехвърлянето на поне първичното изображение на продукта е доста разпространено case при импортиране на данни.
При добавянето на изображение чрез административния панел, картинката първо се запазва в временно каталога (./pub/media/tmp/catalog/product) и само при запазването на продукта, се премества в медийната каталог (./pub/media/catalog/product). Освен това, при добавянето чрез административния панел, на изображението се задават етикети 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);Причината е, че медията се свързва само след предварителното запазване на продукта и последващото му извличане от репозиторията. И е необходимо да се посочи атрибутът label при добавяне на записа в медийната галерия на продукта (иначе получаваме изключение. Неопределённый индекс: label в .../module-catalog/Model/Product/Gallery/CreateHandler.php на строке 516).
Категории
Често структура категориите на магазина и backend приложението или разположението им на продуктите може значително да се различават. Стратегиите за пренасяне на данни за категориите и продуктите в тях зависят от множество фактори. В този пример ще следвам следното:
- категориите на backend и магазина се съпоставят по име;
- ако се импортира категория, която не съществува в магазина, тя се създава под кореновата категория (
Default Category) и нейното последващо позициониране в каталога на магазина се предполага ръчно; - привързването на продукта към категория се извършва само при неговото създаване в магазина (първия импорт);
Основната информация за категорията се намира в таблицата catalog_category_entity (каталог на категориите). Създаване на категория в Magento:
/** @var MagentoCatalogApiDataCategoryInterfaceFactory $factCat */
/** @var MagentoCatalogApiCategoryRepositoryInterface $repoCat */
$cat = $factCat->create();
$cat->setName($name);
$cat->setIsActive(true);
$repoCat->save($cat);Привързването на продукта към категория се извършва по ID на категория и SKU на продукта:
/** @var MagentoCatalogModelCategoryProductLinkFactory $factCatProdLink */
/** @var MagentoCatalogApiCategoryLinkRepositoryInterface $repoCatLink */
$link = $factCatProdLink->create();
$link->setCategoryId($catMageId);
$link->setSku($prodSku);
$repoCatLink->save($link);Общо
Написването на код за добавяне на продукт в Magento 2 по програмен път е доста лесно. Всичко, изложено по-горе, събрах в демо модул ««. В модула има само една конзолна команда fl32:import:prod, която импортира продукти, описани в JSON файл ««:
[
{
"sku": "...",
"name": "...",
"desc": "...",
"desc_short": "...",
"price": ...,
"qty": ...,
"categories": ["..."],
"image_path": "..."
}
]Снимките за импортиране се намират в каталога . /etc/data/img.
Времето за импорт на 10 продукта по този начин е около 10 секунди на моя лаптоп. Ако продължим с това, не е трудно да стигнем до извода, че за един час могат да се импортират около 3600 продукта, а за импорт на 100К продукта може да отнеме около 30 часа. Замяната на лаптопа с сервер позволява значително да се подобри ситуацията. Може би дори многократно. Но не в порядъци. Вероятно тази скорост е относително бавна и в известна степен е една от причините за появата на проекта .
Радикално решение за увеличаване на скоростта на вноса може да бъде директното записване в базата данни, но в този случай се губят всички "плюшки", свързани с разширяемостта на Magento — всичко "разширено" ще трябва да правите сами. Въпреки това, то си струва. Ако успея, ще разгледам подхода с директно записване в БД в следващата статия.
Източник: habr.com
