NĂ« UnĂ« pĂ«rshkrova procesin e importit tĂ« produkteve nĂ« Magento 2 nĂ« mĂ«nyrĂ«n standarde â pĂ«rmes modeleve dhe repozitorĂ«ve. MĂ«nyra e zakonshme karakterizohet nga njĂ« shpejtĂ«si shumĂ« e ulĂ«t pĂ«r pĂ«rpunimin e tĂ« dhĂ«nave. NĂ« laptopin tim, rezultonte rreth njĂ« produkt nĂ« sekondĂ«. NĂ« kĂ«tĂ« vazhdim, unĂ« shqyrtoj njĂ« mĂ«nyrĂ« alternative tĂ« importit tĂ« produktit â shkrimin direkt nĂ« bazĂ«, duke anashkaluar mekanizmat standard tĂ« Magento 2 (modelet, fabrikat, repozitorĂ«t). Renditja e hapave qĂ« sigurojnĂ« importin e produkteve mund tĂ« pĂ«rshtatet pĂ«r çdo gjuhĂ« programimi qĂ« mund tĂ« punojĂ« me MySQL.
ShĂ«nim ligjor: NĂ« Magento ekziston funksionalitet i ndĂ«rtuar pĂ«r dhe, shumĂ« gjasĂ«, ju do ta keni mjaft. MegjithatĂ«, nĂ«se ju nevojitet mĂ« shumĂ« kontroll mbi procesin e importit, qĂ« nuk kufizohet vetĂ«m nĂ« pĂ«rgatitjen e skedarĂ«ve CSV pĂ«r atĂ« qĂ« Ă«shtĂ« â mirĂ«seerdhĂ«t nĂ«n kĂ«tĂ« pĂ«rmbajtje.

Kodi që mbetet nga shkrimi i të dy artikujve mund të shihet në moduline Magento "". Ja disa kufizime që kam ndjekur për të thjeshtuar kodin e modulit demo:
- Produktet krijohen vetëm, nuk përditësohen.
- Një depo
- Importohen vetëm emrat e kategorive, pa strukturën e tyre
- Strukturat e të dhënave përputhen me versionin 2.3
JSON për importimin e një produkti të veçantë:
{
"sku": "MVA20D-UBV-3",
"name": "Kapaku për vulosjen VA47-29 IEK",
"desc": "Sigurimi i aksesit në pajisje ...",
"desc_short": "Kapaku për vulosjen VA47-29 IEK është i destinuar për ...",
"price": 5.00,
"qty": 25,
"categories": ["Kategoria 1", "Kategoria 2"],
"image_path": "mva20d_ubv_3.png"
}Përmbledhja e etapave kryesore të importit
- regjistrimi i produktit të vet
- për lidhjen e produktit me ueb-faqen
- atributet bazë të produktit (EAV)
- të dhënat e inventarit (sasia e produktit në depo)
- media (imazhe)
- lidhja me kategoritë e kataloqeve
Regjistrimi i produktit
Informacioni bazë mbi produktin ndodhet në 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`)
)Informacioni minimal i nevojshëm për krijimin e një regjistrimi në regjistrin e produkteve:
attribute_set_idsku
shtesë:
type_idâ nĂ«se nuk e specifikojmĂ«, atĂ«herĂ« do tĂ« pĂ«rdoret 'simple'
Për shkrimin direkt në bazë përdorim adapterin DB të Magento-s vetë:
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;
}Pasi produkti është regjistruar në catalog_product_entity ai bëhet i dukshëm në admin, në gridin e produkteve (Catalog / Products).

Lidhja e produktit me ueb-faqen
Lidhja e produktit me ueb-faqen përcakton në cilat dyqane dhe në cilat vitrina produkti do të jetë i disponueshëm në front.
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);
}
Atributet bazë të produktit
Një produkt i sapo regjistruar nuk ka as emër, as përshkrim. Të gjitha këto bëhen përmes . Ja lista e atributve bazë të produktit që nevojiten për të siguruar që produkti të shfaqet mjaft saktë në front:
emripricedescriptionshort_descriptionstatustax_class_idurl_keyvisibility
Një atribut i veçantë shtohet kështu (detajet e marrjes së identifikatorit dhe tipit të atributit sipas kodit të tij janë lënë jashtë):
public function create($prodId, $attrCode, $attrValue)
{
$attrId = /* merr ID-në e atributit sipas kodit të atributit */
$attrType = /* merr tipin e atributit [datetime|decimal|int|text|varchar]) sipas kodit të atributit */
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,
/* vendos të gjitha atributet në pamjen e depozitës me id=0 (admin) */
'store_id' => 0,
'value' => $attrValue
];
$conn->insert($table, $bind);
}
}Përmes kodit të atributit përcaktojmë ID-në e tij dhe tipin e të dhënave (datetime, decimal, int, text, varchar), pastaj në tabelën përkatëse shkruajmë të dhënat për pamjen administrative (store_id = 0).
Pasi t'i kemi shtuar atributet e mësipërme produktit, rezultati është ky skenar në admin:

Të dhënat për inventar
Duke filluar nga versioni 2.3 në Magento, ekzistojnë paralelisht dy grupe tabelash që sigurojnë ruajtjen e informacionit të inventarit (sasia e produktit):
cataloginventory_*: struktura e vjetĂ«r;inventory_*: struktura e re (MSI â Multi Source Inventory);
Të dhënat e inventarit duhen shtuar në të dy strukturat, pasi struktura e re ende nuk është plotësisht e pavarur nga e vjetra (duket shumë se për default depon në strukturën e re është përfshirë tabela cataloginventory_stock_status si inventory_stock_1).
cataloginventory_
Kur zhvillohet Magneto 2.3 fillimisht kemi 2 regjistrime nĂ« store_website, qĂ« pĂ«rkon me dy faqe â administrimin dhe faqen kryesore tĂ« klientit:
website_id|code |name |sort_order|default_group_id|is_default|
----------|-----|------------|----------|----------------|----------|
0|admin|Admin | 0| 0| 0|
1|base |Main Website| 0| 1| 1|Në tabelën cataloginventory_stock kemi vetëm një regjistrim:
stock_id|website_id|stock_name|
--------|----------|----------|
1| 0|Default |Pra, në strukturën e vjetër kemi vetëm një «depo» (stock) dhe ajo është e lidhur me faqen administrative të website-it. Shtimi përmes adminit i burimeve të reja sources/stocks në MSI (strukturën e re) nuk çon në shfaqjen e regjistrimeve të reja në cataloginventory_stock.
Të dhënat e inventarit të produkteve në strukturën e vjetër fillimisht shkruhen në tabelat:
cataloginventory_stock_itemcataloginventory_stock_status
cataloginventory_stock_item
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,
/* ne përdorim vetëm një depo në strukturën 'cataloginventory' si parazgjedhje */
'stock_id' => 1,
'qty' => $qty,
'is_qty_decimal' => $isQtyDecimal,
'is_in_stock' => $isInStock,
/* depoja parazgjedhëse është e lidhur me faqen admin (shih `cataloginventory_stock`) */
'website_id' => 0
];
$conn->insert($table, $bind);
}cataloginventory_stock_status
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,
/* ne përdorim vetëm një depo në strukturën 'cataloginventory' si parazgjedhje */
'stock_id' => 1,
'qty' => $qty,
'stock_status' => MagentoCatalogInventoryApiDataStockStatusInterface::STATUS_IN_STOCK,
/* depoja parazgjedhëse është e lidhur me faqen admin (shih `cataloginventory_stock`) */
'website_id' => 0
];
$conn->insert($table, $bind);
}inventory_
Fillimisht struktura e re për ruajtjen e të dhënave të inventarit përmban 1 «burimi» (inventory_source):
source_code|name |enabled|description |latitude|longitude|country_id|...|
default |Default Source| 1|Default Source|0.000000| 0.000000|US |...|dhe një «depo» (inventory_stock):
stock_id|name |
--------|-------------|
1|Default Stock|«Burimi» paraqet një depo fizike për produktet (regjistrimi përmban koordinatat fizike dhe adresën postare). «Depo» paraqet një bashkim logjik të disa «burimeve» (inventory_source_stock_link)
link_id|stock_id|source_code|priority|
-------|--------|-----------|--------|
1| 1|default | 1|në nivelin e cilit ndodhet lidhja me kanalin e shënegjohur (inventory_stock_sales_channel)
type |code|stock_id|
-------|----|--------|
website|base| 1|Duke u bazuar nĂ« strukturĂ«n e tĂ« dhĂ«nave, parashikohen lloje tĂ« ndryshme kanalĂ«sh tĂ« shitjes, por pĂ«r parazgjedhjen pĂ«rdoret vetĂ«m lidhja «stock«-«website» (lidhja me web-faqen ndodh sipas kodit tĂ« web-faqes â bazĂ«).
NjĂ« «depo» mund tĂ« lidhet me disa «burime«, dhe njĂ« «burimi» â me disa «depo» (marrĂ«dhĂ«nie «shumĂ« me shumë»). PĂ«rjashtimet janĂ« defaultâĂ«t «burimi» dhe «depo«. Ato nuk ribindĂ«n me entitete tĂ« tjera (njĂ« kufizim nĂ« nivelin e kodit â del njĂ« gabim «Can not save link related to Default Source or Default Stock«). MĂ« shumĂ« detaje rreth strukturĂ«s MSI nĂ« Magento 2 mund tĂ« lexohen nĂ« artikullin ««.
Do tĂ« pĂ«rdor konfigurimin e default dhe do tĂ« shtoj tĂ« gjitha informacionet e inventarit nĂ« burimin default, i cili Ă«shtĂ« aktivizuar nĂ« kanalin e shitjes, tĂ« lidhur me faqen e web-it me kodin bazĂ« (pĂ«rkon me pjesĂ«n klientore tĂ« dyqanit â shih. 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);
}Pas shtimit të të dhënave të inventarit në produkt në admin, duket kështu:

Media
Kur shtoni manualisht imazhe në produkt përmes adminit, informacioni përkatës regjistrohet në tabelat e mëposhtme:
catalog_product_entity_media_gallery: regjistri i mediave (imazhe dhe video-fajla);catalog_product_entity_media_gallery_value: lidhje e mediave me produktet dhe ekspozitat (lokalizimi);catalog_product_entity_media_gallery_value_to_entity: lidhje e mediave vetëm me produktet (ndoshta, përmbajtja default e mediave për produktin);catalog_product_entity_varchar: këtu ruhen rolet, në të cilat përdoret imazhi;
dhe vetĂ« imazhet ruhen nĂ« katalog ./pub/media/catalog/product/x/y/, ku x dhe y â shkronjat e para dhe tĂ« dyta tĂ« emrit tĂ« skedarit tĂ« imazhit. PĂ«r shembull, skedari image.png duhet tĂ« ruhet si ./pub/media/catalog/product/i/m/image.png, nĂ« mĂ«nyrĂ« qĂ« platforma tĂ« Mund ta pĂ«rdorĂ« si imazh kur pĂ«rshkruan produkte nga katalogu.
catalog_product_entity_media_gallery
Regjistrojmë skedarin e publikuar në ./pub/media/catalog/product/ skedari mediatik (procesi i ngarkimit të skedarit në këtë artikull nuk diskutohet):
function createMediaGallery($imgPathPrefixed)
{
$attrId = /* merr ID-në e atributit me kodin e atributit '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' ose 'video' */
'media_type' => 'image',
'disabled' => false
];
$conn->insert($table, $bind);
$result = $conn->lastInsertId($table);
return $result;
}Kur regjistrohet, skedarit të ri mediatik i jepet një identifikues.
catalog_product_entity_media_gallery_value
Lidhim skedarin e regjistruar med produktin për vitrinën default:
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,
/* përdor pamjen e dyqanit Admin si parazgjedhje */
'store_id' => 0,
'entity_id' => $prodId,
'label' => null,
/* ne kemi vetëm një imazh */
'position' => 1,
'disabled' => false
];
$conn->insert($table, $bind);
}catalog_product_entity_media_gallery_value_to_entity
Lidhim skedarin e regjistruar med produktin pa e lidhur me ndonjë dyqan. Nuk është e qartë se ku saktësisht përdoren këto të dhëna dhe pse nuk mund të referohemi në të dhënat e tabelës së mëparshme, por kjo tabelë ekziston dhe të dhënat regjistrohen aty kur shtohet një imazh në produkt. Prandaj, ja kështu.
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
Skedari mediatik mund të përdoret me role të ndryshme (në prindër dërgohet kodi i atributit të përkatës):
- Bazë (
image) - Imazhi i Vogël (
small_image) - Miniatura (
thumbnail) - Imazhi i Swatch (
swatch_image)
Lidhja e roleve me skedarin mediatik ndodh pikĂ«risht nĂ« catalog_product_entity_varchar. Kodi i lidhjes Ă«shtĂ« i ngjashĂ«m me kodin nĂ« seksionin âAtributet bazĂ« tĂ« produktit«.
Pas shtimit të imazhit në produkt në admin, duket kështu:

Kategoritë
Tabelat kryesore, në të cilat ruhen të dhënat për kategoritë:
catalog_category_entity: regjistri i kategorive;catalog_category_product: lidhja e produkteve dhe kategorive;catalog_category_entity_*: vlerat EAV-aatributeve;
Fillimisht, nĂ« njĂ« aplikacion tĂ« zbrazĂ«t Magento, regjistri i kategorive pĂ«rmban 2 kategori (e kam shkurtuar emrin e kolonave: 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|Kategoria me id=1 është rrënja e gjithë katalogut Magento dhe nuk është e disponueshme as në admin as në front. Kategoria me id=2 (Default Category) është kategoria rrënjë për dyqanin kryesor të faqes kryesore (Main Website Store), e cila krijohet gjatë zbatimit të aplikacionit (shih. Admin / Stores / All Stores). Në fakt, vetë kategoria rrënjë e dyqanit në front gjithashtu nuk është e disponueshme, vetëm nënkategoritë e saj.
Duke qenë se tema e këtij artikulli megjithatë është importimi i të dhënave për produktet, nuk do ta përdor lidhjen e drejtpërdrejtë me bazën gjatë krijimit të kategorive, por do të përdor klasat që ofron vetë Magento (modelet dhe repozitoritë). Shkruajta drejtpërdrejt në bazë përdoret vetëm për të lidhur produktin e importuar me kategorinë (përputhja e kategorisë ndodh sipas emrit të saj, gjatë përputhjes nxirret id e kategorisë):
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);
}Pas lidhjes sĂ« produktit me kategoritĂ« âKategoria 1â dhe âKategoria 2â, detajet e produktit nĂ« admin duken mĂ« pak kĂ«shtu:

Veprimet e tjera
Pas përfundimit të importit të të dhënave, duhet të kryhen veprime të tjera:
- indeksimi i të dhënave: thirrje nga konsola
./bin/magento indexer:reindex; - rregjenerimi i URL-ve pĂ«r produktet/kategoritĂ«: mund tĂ« pĂ«rdorĂ«sh zgjerimin â«
Produkte në admin pas përfundimit të veprimeve të tjera:

dhe në front:

Curriculum Vitae
E njĂ«jta grup produktesh (10 copa), si nĂ« artikullin e kaluar, importohet, sĂ« paku, me njĂ« rend mbrapa (1 sekondĂ« ndaj 10). PĂ«r njĂ« vlerĂ«sim mĂ« tĂ« saktĂ« tĂ« shpejtĂ«sisĂ« nevojiten mĂ« shumĂ« produkte â disa qindra, dhe mĂ« mirĂ« mijĂ«ra. MegjithatĂ«, edhe me kĂ«tĂ« madhĂ«si tĂ« vogĂ«l tĂ« tĂ« dhĂ«nave hyrĂ«se mund tĂ« arrijmĂ« nĂ« njĂ« pĂ«rfundim se pĂ«rdorimi i mjeteve tĂ« ofruara nga Magento (modelet dhe repozitoritĂ«) ndikon dukshĂ«m (theksoj â duke!) pĂ«rshpejtojnĂ« zhvillimin e funksionaliteteve tĂ« nevojshme, por gjithashtu (theksoj â duke!) ulin ndjeshĂ«m shbrendjen e tĂ« dhĂ«nave nĂ« bazĂ«n e tĂ« dhĂ«nave.
Si rezultat, uji doli të ishte i lagur dhe kjo nuk është ndonjë shpikje e re. Megjithatë, tani kam kodin për të eksperimentuar më tej dhe ndoshta për të bërë përfundime më interesante.
Burimi: habr.com
