Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

В мурунку макала Мен Magento 2ге өнүмдөрдү импорттоо процессин кадимки жол менен - ​​моделдер жана репозиторийлер аркылуу сүрөттөп бердим. Кадимки ыкмада маалыматтарды иштетүү ылдамдыгы өтө төмөн. Ноутбугум секундасына бир продуктуну чыгарып жатты. Бул уландысында мен продуктту импорттоонун альтернативалуу жолун карап жатам - стандарттуу Magento 2 механизмдерин (модельдер, фабрикалар, репозиторийлер) айланып өтүп, маалымат базасына түз кирүү жолу менен. Продукцияларды импорттоо кадамдарынын ырааттуулугу MySQL менен иштей турган каалаган программалоо тилине ылайыкташтырылышы мүмкүн.

баш тартуу: Magento үчүн даяр функция бар маалыматтарды импорттоо жана, кыязы, бул сага жетиштүү болот. Бирок, эгер сизге импорттоо процессин толук көзөмөлдөө керек болсо, сизде бар нерсеге CSV файлын даярдоо менен чектелбестен, кошко кош келиңиз.

Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

Эки макаланы тең жазуудан келип чыккан кодду Magento модулунда көрүүгө болот "flancer32/mage2_ext_demo_import". Бул жерде мен демо модулдун кодун жөнөкөйлөтүү үчүн кээ бир чектөөлөр бар:

  • Продукциялар жаңыртылган эмес, түзүлөт.
  • Бир кампа
  • Категориянын аталыштары гана импорттолот, алардын түзүмү жок
  • Маалымат структуралары 2.3 версиясына ылайык келет

бир продукт импорттоо үчүн JSON:

{
  "sku": "MVA20D-UBV-3",
  "name": "Заглушка для пломбировки ВА47-29 IEK",
  "desc": "Обеспечение доступа к устройствам ...",
  "desc_short": "Заглушка для пломбировки ВА47-29 IEK предназначена для ...",
  "price": 5.00,
  "qty": 25,
  "categories": ["Категория 1", "Категория 2"],
  "image_path": "mva20d_ubv_3.png"
}

Импорттун негизги этаптарына сереп

  • продуктунун өзүн каттоо
  • продукт менен веб-сайттын ортосундагы байланыш
  • негизги продукт атрибуттары (EAV)
  • инвентаризация маалыматтары (кампадагы продукциянын саны)
  • маалымат каражаттары (сүрөттөр)
  • каталог категориялары менен байланыш

Продукт каттоо

Негизги продукт маалымат табууга болот catalog_product_entity:

CREATE TABLE `catalog_product_entity` (
  `entity_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Entity Id',
  `attribute_set_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Attribute Set ID',
  `type_id` varchar(32) NOT NULL DEFAULT 'simple' COMMENT 'Type ID',
  `sku` varchar(64) DEFAULT NULL COMMENT 'SKU',
  `has_options` smallint(6) NOT NULL DEFAULT '0' COMMENT 'Has Options',
  `required_options` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Required Options',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation Time',
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Update Time',
  PRIMARY KEY (`entity_id`),
  KEY `CATALOG_PRODUCT_ENTITY_ATTRIBUTE_SET_ID` (`attribute_set_id`),
  KEY `CATALOG_PRODUCT_ENTITY_SKU` (`sku`)
)

Продукциянын реестрине жазуу түзүү үчүн зарыл болгон минималдуу маалымат:

  • attribute_set_id
  • sku

кошумча:

  • type_id — эгерде аны тактабасак, анда «жөнөкөй» колдонулат

Түздөн-түз маалымат базасына жазуу үчүн мен Magento DB адаптерин колдоном:

function create($sku, $typeId, $attrSetId)
{
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('catalog_product_entity');
    $bind = [
        'sku' => $sku,
        'type_id' => $typeId,
        'attribute_set_id' => $attrSetId
    ];
    $conn->insert($table, $bind);
    $result = $conn->lastInsertId($table);
    return $result;
}

менен продуктуну каттоодон өткөндөн кийин catalog_product_entity ал администратор панелинде, продукт торунда көрүнүп калат (Каталог/Продукциялар).

Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

Продукт менен веб-сайттын ортосундагы байланыш

Продукциянын сайт менен байланышы продукттун кайсы дүкөндөрдө жана дисплейлерде болорун аныктайт.

function linkToWebsite($prodId, $websiteId)
{
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('catalog_product_website');
    $bind = [
        'product_id' => $prodId,
        'website_id' => $websiteId
    ];
    $conn->insert($table, $bind);
}

Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

Продукциянын негизги атрибуттары

Жаңы катталган продуктунун аты же сүрөттөлүшү азырынча жок. Мунун баары аркылуу ишке ашырылат EAV атрибуттары. Бул жерде продукт алдыңкы бетинде туура көрсөтүлүшү үчүн зарыл болгон негизги продукт атрибуттарынын тизмеси:

  • name
  • price
  • description
  • short_description
  • status
  • tax_class_id
  • url_key
  • visibility

Мындай өнүмгө өзүнчө атрибут кошулат (анын кодунан атрибуттун идентификаторун жана түрүн алуунун чоо-жайы көрсөтүлбөйт):

public function create($prodId, $attrCode, $attrValue)
{
    $attrId = /* get attribute ID by attribute code */
    $attrType = /* get attribute type [datetime|decimal|int|text|varchar]) by attribute code */
    if ($attrId) {
        /** @var MagentoFrameworkAppResourceConnection $this->resource */
        /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
        $conn = $this->resource->getConnection();
        $tblName = 'catalog_product_entity_' . $attrType;
        $table = $this->resource->getTableName($tblName);
        $bind = [
            'attribute_id' => $attrId,
            'entity_id' => $prodId,
            /* put all attributes to default store view with id=0 (admin) */
            'store_id' => 0,
            'value' => $attrValue
        ];
        $conn->insert($table, $bind);
    }
}

Атрибут кодун колдонуп, анын id жана маалымат түрүн аныктайбыз (datetime, decimal, int, text, varchar), андан кийин административдик терезе үчүн маалыматтарды тиешелүү таблицага жазыңыз (store_id = 0).

Жогорудагы атрибуттарды продуктуга кошкондон кийин, сиз администратор панелинен бул сүрөттү аласыз:

Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

Инвентаризация маалыматтары

Magento 2.3 версиясынан баштап инвентаризациялык маалыматты сактоону камсыз кылган эки параллелдүү таблицалар топтому бар (продукциянын саны):

  • cataloginventory_*: эски түзүлүш;
  • inventory_*: жаңы структура (MSI - Multi Source Inventory);

Сиз инвентаризация маалыматтарын эки түзүмгө кошуу керек, анткени жаңы структура али эскисинен толук көз каранды эмес (бул үчүн болушу мүмкүн default жаңы структурада склад үстөл тартылган cataloginventory_stock_status катары inventory_stock_1).

каталогу_

Magneto 2.3 орнотууда бизде алгач 2 жазуу бар store_website, эки сайтка туура келет - административдик жана негизги кардар:

website_id|code |name        |sort_order|default_group_id|is_default|
----------|-----|------------|----------|----------------|----------|
         0|admin|Admin       |         0|               0|         0|
         1|base |Main Website|         0|               1|         1|

Таблица cataloginventory_stock бизде бир гана жазуу бар:

stock_id|website_id|stock_name|
--------|----------|----------|
       1|         0|Default   |

Башкача айтканда, биздин эски структурабызда бир гана «склад» бар (stock) жана ал административдик веб-сайтка шилтемеленген. Администратор панели аркылуу жаңыларды кошуу sources/stocks MSIде (жаңы структура) жаңы жазууларды алып келбейт cataloginventory_stock.

Эски структурадагы продуктулар жөнүндө инвентаризациялык маалыматтар таблицаларда жазылат:

  • cataloginventory_stock_item
  • cataloginventory_stock_status

каталогдогу_запас_зат

function createOldItem($prodId, $qty)
{
    $isQtyDecimal = (((int)$qty) != $qty);
    $isInStock = ($qty > 0);
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('cataloginventory_stock_item');
    $bind = [
        'product_id' => $prodId,
        /* we use one only stock in 'cataloginventory' structure by default */
        'stock_id' => 1,
        'qty' => $qty,
        'is_qty_decimal' => $isQtyDecimal,
        'is_in_stock' => $isInStock,
        /* default stock is bound to admin website (see `cataloginventory_stock`) */
        'website_id' => 0
    ];
    $conn->insert($table, $bind);
}

каталогдун_запас_статусу

function createOldStatus($prodId, $qty)
{
    $isInStock = ($qty > 0);
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('cataloginventory_stock_status');
    $bind = [
        'product_id' => $prodId,
        /* we use one only stock in 'cataloginventory' structure by default */
        'stock_id' => 1, 
        'qty' => $qty,
        'stock_status' => MagentoCatalogInventoryApiDataStockStatusInterface::STATUS_IN_STOCK,
        /* default stock is bound to admin website (see `cataloginventory_stock`) */
        'website_id' => 0 
    ];
    $conn->insert($table, $bind);
}

инвентарь_

Башында, инвентаризациялык маалыматтарды сактоо үчүн жаңы структура 1 "булак«(inventory_source):

source_code|name          |enabled|description   |latitude|longitude|country_id|...|
-----------|--------------|-------|--------------|--------|---------|----------|...|
default    |Default Source|      1|Default Source|0.000000| 0.000000|US        |...|

жана бир "товар сактоочу бөлмө«(inventory_stock):

stock_id|name         |
--------|-------------|
       1|Default Stock|

«булак» өнүмдөрдүн физикалык сактагычын билдирет (жазууда физикалык координаттар жана почта дареги камтылган). "товар сактоочу бөлмө"бул бир нече "булактардын" логикалык бирикмеси (inventory_source_stock_link)

link_id|stock_id|source_code|priority|
-------|--------|-----------|--------|
      1|       1|default    |       1|

сатуу каналына байланыш пайда болгон деңгээлде (inventory_stock_sales_channel)

type   |code|stock_id|
-------|----|--------|
website|base|       1|

Маалымат түзүмүнө караганда, сатуу каналдарынын ар кандай түрлөрү болжолдонот, бирок демейки боюнча гана байланыш "акция"-"сайты"(веб-сайтка шилтеме веб-сайттын кодун ээрчийт - base).

Бир "товар сактоочу бөлмө"бир нече менен байланыштырылышы мүмкүн"булактар"жана бир "булак"- бир нечеге"кампалар"(көптөн көпкө байланыш). Өзгөчө жагдайлар демейки болуп саналат'булак"Ал эми"товар сактоочу бөлмө". Алар башка жактар ​​менен кайра байланыштырылбайт (код деңгээлинде чектөө - ката "Демейки булакка же Демейки запаска байланыштуу шилтемени сактоо мүмкүн эмес"). Magento 2деги MSI түзүмү жөнүндө көбүрөөк маалыматты макаладан тапса болот "CQRS жана Event Sourcing аркылуу кампаларды башкаруу системасы. Дизайн".

Мен демейки конфигурацияны колдоном жана бардык инвентаризация маалыматын булакка кошом default, коду менен веб-сайт менен байланышкан сатуу каналына тартылган base (дүкөндүн алдыңкы жагына туура келет - караңыз store_website):

function createNewItem($sku, $qty)
{
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('inventory_source_item');
    $bind = [
        'source_code' => 'default',
        'sku' => $sku,
        'quantity' => $qty,
        'status' => MagentoInventoryApiApiDataSourceItemInterface::STATUS_IN_STOCK
    ];
    $conn->insert($table, $bind);
}

Администратордук панелдеги продуктка инвентаризация маалыматтарын кошкондон кийин, сиз бул сүрөттү аласыз:

Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

маалымат каражаттары

Администратор панели аркылуу буюмга сүрөттү "кол менен" кошкондо, тиешелүү маалымат төмөнкү таблицаларда жазылат:

  • catalog_product_entity_media_gallery: медиа реестри (сүрөттөр жана видео файлдар);
  • catalog_product_entity_media_gallery_value: ММКларды продуктылар жана витриналар менен байланыштыруу (локалдаштыруу);
  • catalog_product_entity_media_gallery_value_to_entity: медианы продуктыларга гана байланыштыруу (болжол менен продукт үчүн демейки медиа мазмуну);
  • catalog_product_entity_varchar: Сүрөт колдонулган ролдор бул жерде сакталат;

жана сүрөттөрдүн өзү каталогго сакталат ./pub/media/catalog/product/x/y/кайда x и y — сүрөт файлынын аталышынын биринчи жана экинчи тамгалары. Мисалы, файл image.png катары сакталышы керек ./pub/media/catalog/product/i/m/image.png, платформа каталогдогу өнүмдөрдү сүрөттөп жатканда аны сүрөт катары колдоно алышы үчүн.

Каттоо жарыяланды ./pub/media/catalog/product/ медиа файл (файлдын өзүн жайгаштыруу процесси бул макалада каралбайт):

function createMediaGallery($imgPathPrefixed)
{
    $attrId = /* get attribute ID by attribute code 'media_gallery' */
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('catalog_product_entity_media_gallery');
    $bind = [
        'attribute_id' => $attrId,
        'value' => $imgPathPrefixed,
        /* 'image' or 'video' */
        'media_type' => 'image',
        'disabled' => false
    ];
    $conn->insert($table, $bind);
    $result = $conn->lastInsertId($table);
    return $result;
}

Катталганда жаңы медиа файлга идентификатор ыйгарылат.

Биз катталган медиа файлды демейки дүкөндүн маңдайкы бетине тиешелүү продукт менен байланыштырабыз:

function createGalleryValue($mediaId, $prodId)
{
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('catalog_product_entity_media_gallery_value');
    $bind = [
        'value_id' => $mediaId,
        /* use admin store view by default */
        'store_id' => 0,
        'entity_id' => $prodId,
        'label' => null,
        /* we have one only image */
        'position' => 1,
        'disabled' => false
    ];
    $conn->insert($table, $bind);
}

Биз катталган медиа файлды эч кандай дүкөндүн маңдайкы жагына байланбастан тиешелүү продукт менен байланыштырабыз. Бул маалымат так кайда колдонулганы жана эмне үчүн мурунку таблицадагы маалыматтарга жетүү мүмкүн эместиги түшүнүксүз, бирок бул таблица бар жана продуктка сүрөт кошулганда маалыматтар ага жазылат. Ошентип бүттү.

function createGalleryValueToEntity($mediaId, $prodId)
{
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('catalog_product_entity_media_gallery_value_to_entity');
    $bind = [
        'value_id' => $mediaId,
        'entity_id' => $prodId
    ];
    $conn->insert($table, $bind);
}

catalog_product_entity_varchar

Медиа файлды ар кандай ролдор менен колдонсо болот (тиешелүү атрибут коду кашаада көрсөтүлгөн):

  • Негизги(image)
  • Кичинекей сүрөт (small_image)
  • Эскиз (thumbnail)
  • Swatch Image (swatch_image)

Ролдорду медиа файлга байланыштыруу дал ушундай болот catalog_product_entity_varchar. Байланыш коду ""дагы кодго окшош.Продукциянын негизги атрибуттары".

Администратор панелинде продуктка сүрөт кошкондон кийин, ал төмөнкүдөй болот:

Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

Категории

Категория боюнча маалыматтарды камтыган негизги таблицалар:

  • catalog_category_entity: категориялардын реестри;
  • catalog_category_product: продуктылар жана категориялар ортосундагы байланыш;
  • catalog_category_entity_*: EAV атрибутунун маанилери;

Башында, бош Magento тиркемесинде категория реестри 2 категорияны камтыйт (мен мамычанын аталыштарын кыскарттым: crt - created_at, upd - updated_at):

entity_id|attribute_set_id|parent_id|crt|upd|path|position|level|children_count|
---------|----------------|---------|---|---|----|--------|-----|--------------|
        1|               3|        0|...|...|1   |       0|    0|             1|
        2|               3|        1|...|...|1/2 |       1|    1|             0|

Идентификатор=1 болгон категория бүт Magento каталогунун тамыры жана администратор панелинде да, алдыңкы бетинде да жеткиликтүү эмес. id=2 болгон категория (Демейки категория) негизги сайттын негизги дүкөнүнүн түпкү категориясы (Негизги сайт дүкөнү) колдонмо орнотулганда түзүлгөн (караңыз. Админ / Дүкөндөр / Бардык дүкөндөр). Анын үстүнө, дүкөндүн түпкү категориясы да алдыңкы жакта эмес, анын субкатегориялары гана.

Бул макаланын темасы дагы эле өнүмдөр боюнча маалыматтарды импорттоо болгондуктан, мен категорияларды түзүүдө маалымат базасына түз кирүүнү колдонбойм, бирок Magento өзү берген класстарды (моделдер жана репозиторийлер) колдоном. Маалыматтар базасына түз кирүү импорттолгон продуктуну категория менен байланыштыруу үчүн гана колдонулат (категория анын аты менен дал келет, ал эми категориянын идентификатору дал келүү учурунда чыгарылат):

function create($prodId, $catId)
{
    /** @var MagentoFrameworkAppResourceConnection $this->resource */
    /** @var MagentoFrameworkDBAdapterPdoMysql $conn */
    $conn = $this->resource->getConnection();
    $table = $this->resource->getTableName('catalog_category_product');
    $bind = [
        'category_id' => $catId,
        'product_id' => $prodId,
    ];
    $conn->insert($table, $bind);
}

"1-категория" жана "2-категория" категорияларына продукт шилтемесин кошкондон кийин, администратор панелиндеги продукттун чоо-жайы төмөнкүдөй көрүнөт:

Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

Дагы аракеттер

Маалыматтарды импорттоо аяктагандан кийин, сиз төмөнкү кошумча кадамдарды аткарышыңыз керек:

  • маалыматтарды индекстөө: консолдо чалуу ./bin/magento indexer:reindex;
  • өнүмдөр/категориялар үчүн URL'дерди калыбына келтирүү: сиз кеңейтүүнү колдоно аласыз "elgentos/regenerate-catalog-urls«

Кошумча аракеттерди аткаргандан кийин администратор панелиндеги өнүмдөр:

Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

жана алдыда:

Magento 2: өнүмдөрдү түздөн-түз маалымат базасына импорттоо

на

Мурунку макаладагыдай эле буюмдардын (10 даана) топтому, жок эле дегенде, ылдамыраак (1 секундага каршы) импорттолот. Ылдамдыкты такыраак баалоо үчүн сизге көбүрөөк сандагы буюмдар керек - бир нече жүздөгөн, же андан да жакшыраак миңдеген. Бирок, киргизүү маалыматтарынын ушунчалык кичинекей өлчөмү менен да, биз Magento тарабынан берилген куралдарды (моделдер жана репозиторийлер) колдонуу маанилүү деп тыянак чыгарууга болот (мен баса белгилейм - көп!) талап кылынган функциялардын өнүгүшүн тездетүү, бирок ошол эле учурда олуттуу (мен баса белгилейм - көп!) маалыматтардын маалымат базасына түшүү ылдамдыгын азайтыңыз.

Натыйжада, суу нымдуу болуп чыкты жана бул ачылыш эмес. Бирок, азыр менде ойной турган код бар жана балким дагы кызыктуу тыянактарга келем.

Source: www.habr.com