Prohoster > Blog > quản lý > Magento 2: nhập sản phẩm trực tiếp vào cơ sở dữ liệu
Magento 2: nhập sản phẩm trực tiếp vào cơ sở dữ liệu
В bài viết trước Tôi đã mô tả quá trình nhập sản phẩm vào Magento 2 theo cách thông thường - thông qua các mô hình và kho lưu trữ. Phương pháp thông thường có tốc độ xử lý dữ liệu rất thấp. Máy tính xách tay của tôi sản xuất khoảng một sản phẩm mỗi giây. Trong phần tiếp theo này, tôi xem xét một cách khác để nhập sản phẩm - bằng cách nhập trực tiếp vào cơ sở dữ liệu, bỏ qua các cơ chế tiêu chuẩn của Magento 2 (mô hình, nhà máy, kho lưu trữ). Trình tự các bước để nhập sản phẩm có thể được điều chỉnh cho phù hợp với bất kỳ ngôn ngữ lập trình nào có thể hoạt động với MySQL.
Từ chối trách nhiệm: Magento có sẵn chức năng cho nhập dữ liệu và rất có thể, nó sẽ là đủ đối với bạn. Tuy nhiên, nếu bạn cần kiểm soát hoàn toàn hơn quá trình nhập, không giới hạn ở việc chuẩn bị tệp CSV cho những gì bạn có, chào mừng bạn đến với cat.
Mã thu được từ việc viết cả hai bài viết có thể được xem trong mô-đun Magento "flacer32/mage2_ext_demo_import". Dưới đây là một số hạn chế mà tôi đã tuân theo để đơn giản hóa mã mô-đun demo:
Sản phẩm chỉ được tạo ra, không được cập nhật.
Một kho
Chỉ tên danh mục được nhập mà không có cấu trúc của chúng
Cấu trúc dữ liệu tuân theo phiên bản 2.3
JSON để nhập một sản phẩm:
{
"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"
}
Tổng quan về các giai đoạn chính của nhập khẩu
đăng ký sản phẩm
kết nối giữa sản phẩm và website
Thuộc tính sản phẩm cơ bản (EAV)
Dữ liệu tồn kho (số lượng sản phẩm trong kho)
phương tiện truyền thông (hình ảnh)
kết nối với danh mục danh mục
Đăng ký sản phẩm
Thông tin cơ bản về sản phẩm có thể được tìm thấy trong 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`)
)
Thông tin tối thiểu cần thiết để tạo một mục trong sổ đăng ký sản phẩm là:
attribute_set_id
sku
thêm vào:
type_id — nếu chúng ta không chỉ định nó thì 'đơn giản' sẽ được sử dụng
Để ghi trực tiếp vào cơ sở dữ liệu, tôi sử dụng bộ chuyển đổi DB của chính Magento:
Sản phẩm mới đăng ký chưa có tên hoặc mô tả. Tất cả điều này được thực hiện thông qua Thuộc tính EAV. Dưới đây là danh sách các thuộc tính cơ bản của sản phẩm cần thiết để sản phẩm được hiển thị chính xác ở mặt trước:
name
price
description
short_description
status
tax_class_id
url_key
visibility
Một thuộc tính riêng biệt được thêm vào một sản phẩm như thế này (chi tiết về việc lấy mã định danh và loại thuộc tính từ mã của nó bị bỏ qua):
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);
}
}
Sử dụng mã thuộc tính, chúng tôi xác định id và kiểu dữ liệu của nó (datetime, decimal, int, text, varchar), sau đó ghi dữ liệu cho cửa sổ quản trị vào bảng thích hợp (store_id = 0).
Sau khi thêm các thuộc tính trên vào sản phẩm, bạn sẽ có được hình ảnh này trong bảng quản trị:
Dữ liệu tồn kho
Bắt đầu từ phiên bản 2.3 trong Magento, có hai bộ bảng song song cung cấp khả năng lưu trữ thông tin hàng tồn kho (số lượng sản phẩm):
cataloginventory_*: kết cấu cũ;
inventory_*: cấu trúc mới (MSI - Multi Source Inventory);
Bạn cần thêm dữ liệu hàng tồn kho vào cả hai cấu trúc, bởi vì cấu trúc mới chưa hoàn toàn độc lập với cấu trúc cũ (rất có thể là đối với default kho trong cấu trúc mới có một bảng tham gia cataloginventory_stock_status như inventory_stock_1).
danh mục kiểm kê_
Khi triển khai Magneto 2.3 ban đầu chúng tôi có 2 mục trong store_website, tương ứng với hai trang web - máy khách quản trị và máy khách chính:
Nghĩa là, trong cấu trúc cũ của chúng tôi chỉ có một “nhà kho” (stock) và nó được liên kết với trang web quản trị. Thêm cái mới thông qua bảng quản trị sources/stocks trong MSI (cấu trúc mới) không dẫn đến các mục mới trong cataloginventory_stock.
Số liệu tồn kho về sản phẩm theo cơ cấu cũ ban đầu được ghi vào các bảng:
cataloginventory_stock_item
cataloginventory_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,
/* 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);
}
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,
/* 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);
}
hàng tồn kho_
Ban đầu, cấu trúc mới để lưu trữ dữ liệu hàng tồn kho chứa 1 "nguồn'(inventory_source):
«Nguồn» thể hiện việc lưu trữ vật lý cho các sản phẩm (bản ghi chứa tọa độ vật lý và địa chỉ gửi thư). "Kho"là sự kết hợp logic của một số" nguồn "(inventory_source_stock_link)
ở cấp độ xảy ra kết nối với kênh bán hàng (inventory_stock_sales_channel)
type |code|stock_id|
-------|----|--------|
website|base| 1|
Đánh giá theo cấu trúc dữ liệu, nhiều loại kênh bán hàng khác nhau được giả định, nhưng theo mặc định chỉ có kết nối “cổ phần"-"trang mạng"(liên kết đến trang web tuân theo mã trang web - base).
Một "kho"có thể được liên kết với một số"nguồn"và một "nguồn" - một số "kho hàng"(mối quan hệ nhiều-nhiều). Các ngoại lệ là mặc định "nguồn"Và"kho". Chúng không được liên kết lại với các thực thể khác (hạn chế ở cấp mã - lỗi “Không thể lưu liên kết liên quan đến Nguồn mặc định hoặc Kho mặc định"). Bạn có thể tìm thêm thông tin chi tiết về cấu trúc MSI trong Magento 2 trong bài viết “Hệ thống quản lý kho sử dụng CQRS và Event Sourcing. Thiết kế".
Mình sẽ sử dụng cấu hình mặc định và thêm toàn bộ thông tin kho vào nguồn default, tham gia kênh bán hàng liên kết với website bằng mã base (tương ứng với mặt trước của cửa hàng - xem store_website):
Sau khi thêm dữ liệu hàng tồn kho vào sản phẩm trong bảng quản trị, bạn sẽ có được hình ảnh này:
Phương tiện truyền thông
Khi thêm hình ảnh vào sản phẩm “thủ công” thông qua bảng quản trị, thông tin liên quan sẽ được ghi vào các bảng sau:
catalog_product_entity_media_gallery: đăng ký phương tiện (tệp hình ảnh và video);
catalog_product_entity_media_gallery_value: liên kết phương tiện truyền thông với sản phẩm và trưng bày (bản địa hóa);
catalog_product_entity_media_gallery_value_to_entity: chỉ liên kết phương tiện với sản phẩm (có lẽ là nội dung phương tiện mặc định cho sản phẩm);
catalog_product_entity_varchar: Các vai trò sử dụng hình ảnh được lưu trữ ở đây;
và bản thân hình ảnh được lưu vào thư mục ./pub/media/catalog/product/x/y/Đâu x и y — chữ cái đầu tiên và thứ hai của tên tệp hình ảnh. Ví dụ: tập tin image.png nên được lưu dưới dạng ./pub/media/catalog/product/i/m/image.png, để nền tảng có thể sử dụng nó làm hình ảnh khi mô tả các sản phẩm trong danh mục.
catalog_product_entity_media_gallery
Đăng ký được đăng trong ./pub/media/catalog/product/ tập tin media (quá trình đặt tập tin không được thảo luận trong bài viết này):
Chúng tôi liên kết tệp phương tiện đã đăng ký với sản phẩm tương ứng mà không bị ràng buộc với bất kỳ mặt tiền cửa hàng nào. Không rõ chính xác dữ liệu này được sử dụng ở đâu và tại sao không thể truy cập dữ liệu từ bảng trước đó, nhưng bảng này tồn tại và dữ liệu được ghi vào đó khi hình ảnh được thêm vào sản phẩm. À chính nó đấy.
Một tệp phương tiện có thể được sử dụng với các vai trò khác nhau (mã thuộc tính tương ứng được chỉ định trong ngoặc đơn):
Căn cứ(image)
Hình Ảnh Nhỏ (small_image)
Hình nhỏ (thumbnail)
Mẫu ảnh (swatch_image)
Liên kết các vai trò với một tệp phương tiện chính xác là những gì xảy ra trong catalog_product_entity_varchar. Mã ràng buộc tương tự như mã trong phần "Thuộc tính sản phẩm cơ bản".
Sau khi thêm hình ảnh vào sản phẩm trong bảng quản trị, nó trông như thế này:
Thể loại
Các bảng chính chứa dữ liệu theo danh mục:
catalog_category_entity: đăng ký danh mục;
catalog_category_product: kết nối giữa sản phẩm và chủng loại;
catalog_category_entity_*: Giá trị thuộc tính EAV;
Ban đầu, trong một ứng dụng Magento trống, sổ đăng ký danh mục chứa 2 danh mục (tôi đã rút ngắn tên cột: crt - created_at, upd - updated_at):
Danh mục có id=1 là thư mục gốc của toàn bộ danh mục Magento và không có sẵn trong bảng quản trị hoặc trên trang đầu. Danh mục có id=2 (Danh mục Mặc định) là danh mục gốc cho cửa hàng chính của trang web chính (Cửa hàng trang web chính) được tạo khi ứng dụng được triển khai (xem. Quản trị / Cửa hàng / Tất cả cửa hàng). Hơn nữa, bản thân danh mục gốc của cửa hàng cũng không có ở phía trước, chỉ có các danh mục phụ của nó.
Vì chủ đề của bài viết này vẫn là nhập dữ liệu về sản phẩm nên tôi sẽ không sử dụng tính năng nhập trực tiếp vào cơ sở dữ liệu khi tạo danh mục mà sẽ sử dụng các lớp do chính Magento cung cấp (model và kho lưu trữ). Việc nhập trực tiếp vào cơ sở dữ liệu chỉ được sử dụng để liên kết sản phẩm đã nhập với một danh mục (danh mục được khớp theo tên của nó và id danh mục được truy xuất trong quá trình khớp):
Các sản phẩm trong bảng quản trị sau khi thực hiện các thao tác bổ sung:
và ở phía trước:
Tóm tắt thông tin
Cùng một bộ sản phẩm (10 chiếc) như trong bài viết trước được nhập nhanh hơn ít nhất một bậc (1 giây so với 10). Để ước tính chính xác hơn tốc độ, bạn cần số lượng sản phẩm lớn hơn - vài trăm hoặc tốt hơn là hàng nghìn. Tuy nhiên, ngay cả với kích thước dữ liệu đầu vào nhỏ như vậy, chúng ta có thể kết luận rằng việc sử dụng các công cụ do Magento (mô hình và kho lưu trữ) cung cấp là rất đáng kể (tôi nhấn mạnh - nhiều!) Tăng tốc độ phát triển các chức năng cần thiết, nhưng đồng thời cũng đáng kể (tôi nhấn mạnh - nhiều!) Giảm tốc độ dữ liệu vào cơ sở dữ liệu.
Kết quả là nước trở nên ướt và đây không phải là một điều mặc khải. Tuy nhiên, bây giờ tôi đã có mã để sử dụng và có lẽ sẽ đưa ra một số kết luận thú vị hơn.