Câu trả lời:
Đây là cách tiếp cận tôi đã đưa ra để xử lý các tùy chọn thuộc tính. Lớp người trợ giúp:
<?php
namespace My\Module\Helper;
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
/**
* @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface
*/
protected $attributeRepository;
/**
* @var array
*/
protected $attributeValues;
/**
* @var \Magento\Eav\Model\Entity\Attribute\Source\TableFactory
*/
protected $tableFactory;
/**
* @var \Magento\Eav\Api\AttributeOptionManagementInterface
*/
protected $attributeOptionManagement;
/**
* @var \Magento\Eav\Api\Data\AttributeOptionLabelInterfaceFactory
*/
protected $optionLabelFactory;
/**
* @var \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory
*/
protected $optionFactory;
/**
* Data constructor.
*
* @param \Magento\Framework\App\Helper\Context $context
* @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository
* @param \Magento\Eav\Model\Entity\Attribute\Source\TableFactory $tableFactory
* @param \Magento\Eav\Api\AttributeOptionManagementInterface $attributeOptionManagement
* @param \Magento\Eav\Api\Data\AttributeOptionLabelInterfaceFactory $optionLabelFactory
* @param \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory $optionFactory
*/
public function __construct(
\Magento\Framework\App\Helper\Context $context,
\Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository,
\Magento\Eav\Model\Entity\Attribute\Source\TableFactory $tableFactory,
\Magento\Eav\Api\AttributeOptionManagementInterface $attributeOptionManagement,
\Magento\Eav\Api\Data\AttributeOptionLabelInterfaceFactory $optionLabelFactory,
\Magento\Eav\Api\Data\AttributeOptionInterfaceFactory $optionFactory
) {
parent::__construct($context);
$this->attributeRepository = $attributeRepository;
$this->tableFactory = $tableFactory;
$this->attributeOptionManagement = $attributeOptionManagement;
$this->optionLabelFactory = $optionLabelFactory;
$this->optionFactory = $optionFactory;
}
/**
* Get attribute by code.
*
* @param string $attributeCode
* @return \Magento\Catalog\Api\Data\ProductAttributeInterface
*/
public function getAttribute($attributeCode)
{
return $this->attributeRepository->get($attributeCode);
}
/**
* Find or create a matching attribute option
*
* @param string $attributeCode Attribute the option should exist in
* @param string $label Label to find or add
* @return int
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function createOrGetId($attributeCode, $label)
{
if (strlen($label) < 1) {
throw new \Magento\Framework\Exception\LocalizedException(
__('Label for %1 must not be empty.', $attributeCode)
);
}
// Does it already exist?
$optionId = $this->getOptionId($attributeCode, $label);
if (!$optionId) {
// If no, add it.
/** @var \Magento\Eav\Model\Entity\Attribute\OptionLabel $optionLabel */
$optionLabel = $this->optionLabelFactory->create();
$optionLabel->setStoreId(0);
$optionLabel->setLabel($label);
$option = $this->optionFactory->create();
$option->setLabel($optionLabel);
$option->setStoreLabels([$optionLabel]);
$option->setSortOrder(0);
$option->setIsDefault(false);
$this->attributeOptionManagement->add(
\Magento\Catalog\Model\Product::ENTITY,
$this->getAttribute($attributeCode)->getAttributeId(),
$option
);
// Get the inserted ID. Should be returned from the installer, but it isn't.
$optionId = $this->getOptionId($attributeCode, $label, true);
}
return $optionId;
}
/**
* Find the ID of an option matching $label, if any.
*
* @param string $attributeCode Attribute code
* @param string $label Label to find
* @param bool $force If true, will fetch the options even if they're already cached.
* @return int|false
*/
public function getOptionId($attributeCode, $label, $force = false)
{
/** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */
$attribute = $this->getAttribute($attributeCode);
// Build option array if necessary
if ($force === true || !isset($this->attributeValues[ $attribute->getAttributeId() ])) {
$this->attributeValues[ $attribute->getAttributeId() ] = [];
// We have to generate a new sourceModel instance each time through to prevent it from
// referencing its _options cache. No other way to get it to pick up newly-added values.
/** @var \Magento\Eav\Model\Entity\Attribute\Source\Table $sourceModel */
$sourceModel = $this->tableFactory->create();
$sourceModel->setAttribute($attribute);
foreach ($sourceModel->getAllOptions() as $option) {
$this->attributeValues[ $attribute->getAttributeId() ][ $option['label'] ] = $option['value'];
}
}
// Return option ID if exists
if (isset($this->attributeValues[ $attribute->getAttributeId() ][ $label ])) {
return $this->attributeValues[ $attribute->getAttributeId() ][ $label ];
}
// Return false if does not exist
return false;
}
}
Sau đó, trong cùng một lớp hoặc bao gồm nó thông qua tiêm phụ thuộc, bạn có thể thêm hoặc nhận ID tùy chọn của mình bằng cách gọi createOrGetId($attributeCode, $label)
.
Ví dụ: nếu bạn tiêm My\Module\Helper\Data
như $this->moduleHelper
, thì bạn có thể gọi:
$manufacturerId = $this->moduleHelper->createOrGetId('manufacturer', 'ABC Corp');
Nếu 'ABC Corp' là nhà sản xuất hiện có, nó sẽ lấy ID. Nếu không, nó sẽ thêm nó.
CẬP NHẬT 2016-09-09: Per Ruud N., giải pháp ban đầu đã sử dụng Catalogsetup, dẫn đến lỗi bắt đầu trong Magento 2.1. Giải pháp sửa đổi này bỏ qua mô hình đó, tạo ra tùy chọn và nhãn rõ ràng. Nó nên hoạt động trên 2.0+.
Magento\Eav\Model\ResourceModel\Entity\Attribute::_processAttributeOptions
. Hãy tự mình xem, nếu bạn xóa $option->setValue($label);
câu lệnh khỏi mã của mình, nó sẽ lưu tùy chọn, sau đó khi bạn tìm nạp nó, Magento sẽ trả về giá trị từ mức tăng tự động trên eav_attribute_option
bảng.
đã thử nghiệm trên Magento 2.1.3.
Tôi đã không tìm thấy bất kỳ cách khả thi nào để tạo thuộc tính với các tùy chọn cùng một lúc. Vì vậy, ban đầu chúng ta cần tạo một thuộc tính và sau đó thêm tùy chọn cho nó.
Tiêm theo lớp \ Magento \ Eav \ Setup \ EavSetupFactory
$setup->startSetup();
/** @var \Magento\Eav\Setup\EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttribute(
'catalog_product',
$attributeCode,
[
'type' => 'varchar',
'input' => 'select',
'required' => false,
...
],
);
Hàm addAttribute
không trả về bất cứ thứ gì hữu ích có thể được sử dụng trong tương lai. Vì vậy, sau khi tạo thuộc tính, chúng ta cần lấy chính đối tượng thuộc tính. !!! Quan trọng Chúng tôi cần nó vì chức năng chỉ mong đợi attribute_id
, nhưng không muốn làm việc với attribute_code
.
Trong trường hợp đó, chúng ta cần lấy attribute_id
và chuyển nó vào hàm tạo thuộc tính.
$attributeId = $eavSetup->getAttributeId('catalog_product', 'attribute_code');
Sau đó, chúng ta cần tạo mảng tùy chọn theo cách magento mong đợi:
$options = [
'values' => [
'sort_order1' => 'title1',
'sort_order2' => 'title2',
'sort_order3' => 'title3',
],
'attribute_id' => 'some_id',
];
Ví dụ như:
$options = [
'values' => [
'1' => 'Red',
'2' => 'Yellow',
'3' => 'Green',
],
'attribute_id' => '32',
];
Và chuyển nó vào chức năng:
$eavSetup->addAttributeOption($options);
Sử dụng lớp Magento \ Eav \ Setup \ EavSetupFactory hoặc thậm chí lớp \ Magento \ Catalog \ Setup \ CategorySetupFactory có thể dẫn đến sự cố sau: https://github.com/magento/magento2/issues/4896 .
Các lớp bạn nên sử dụng:
protected $_logger;
protected $_attributeRepository;
protected $_attributeOptionManagement;
protected $_option;
protected $_attributeOptionLabel;
public function __construct(
\Psr\Log\LoggerInterface $logger,
\Magento\Eav\Model\AttributeRepository $attributeRepository,
\Magento\Eav\Api\AttributeOptionManagementInterface $attributeOptionManagement,
\Magento\Eav\Api\Data\AttributeOptionLabelInterface $attributeOptionLabel,
\Magento\Eav\Model\Entity\Attribute\Option $option
){
$this->_logger = $logger;
$this->_attributeRepository = $attributeRepository;
$this->_attributeOptionManagement = $attributeOptionManagement;
$this->_option = $option;
$this->_attributeOptionLabel = $attributeOptionLabel;
}
Sau đó, trong chức năng của bạn làm một cái gì đó như thế này:
$attribute_id = $this->_attributeRepository->get('catalog_product', 'your_attribute')->getAttributeId();
$options = $this->_attributeOptionManagement->getItems('catalog_product', $attribute_id);
/* if attribute option already exists, remove it */
foreach($options as $option) {
if ($option->getLabel() == $oldname) {
$this->_attributeOptionManagement->delete('catalog_product', $attribute_id, $option->getValue());
}
}
/* new attribute option */
$this->_option->setValue($name);
$this->_attributeOptionLabel->setStoreId(0);
$this->_attributeOptionLabel->setLabel($name);
$this->_option->setLabel($this->_attributeOptionLabel);
$this->_option->setStoreLabels([$this->_attributeOptionLabel]);
$this->_option->setSortOrder(0);
$this->_option->setIsDefault(false);
$this->_attributeOptionManagement->add('catalog_product', $attribute_id, $this->_option);
$attributeOptionLabel
và $option
là các lớp ORM; bạn không nên tiêm trực tiếp. Cách tiếp cận phù hợp là tiêm lớp nhà máy của họ, sau đó tạo một thể hiện khi cần thiết. Cũng lưu ý rằng bạn không sử dụng giao diện dữ liệu API một cách nhất quán.
$option->setValue()
vì đó là cho một option_id
trường magento nội bộ trên eav_attribute_option
bàn.
Đối với Magento 2.3.3 Tôi thấy rằng bạn có thể sử dụng phương pháp Magento DevTeam.
bin/magento setup:db-declaration:generate-patch Vendor_Module PatchName
public function __construct( ModuleDataSetupInterface $moduleDataSetup, Factory $configFactory CategorySetupFactory $categorySetupFactory ) { $this->moduleDataSetup = $moduleDataSetup; $this->configFactory = $configFactory; $this->categorySetupFactory = $categorySetupFactory; }
Thêm thuộc tính trong hàm áp dụng ()
public function apply()
{
$categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]);
$categorySetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'custom_layout',
[
'type' => 'varchar',
'label' => 'New Layout',
'input' => 'select',
'source' => \Magento\Catalog\Model\Product\Attribute\Source\Layout::class,
'required' => false,
'sort_order' => 50,
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
'group' => 'Schedule Design Update',
'is_used_in_grid' => true,
'is_visible_in_grid' => false,
'is_filterable_in_grid' => false
]
);
}
Nó giả định rằng bạn có quyền truy cập vào Magento Backend bằng trình duyệt và bạn đang ở trang chỉnh sửa thuộc tính (url trông giống như admin / catalog / sản phẩm_attribution / edit / property_id / XXX / key ..)
Chuyển đến Bảng điều khiển trình duyệt (CTRL + SHIFT + J trên chrome) và dán đoạn mã sau sau khi thay đổi mảng bắt chước .
$jq=new jQuery.noConflict();
var mimim=["xxx","yyy","VALUES TO BE ADDED"];
$jq.each(mimim,function(a,b){
$jq("#add_new_option_button").click();
$jq("#manage-options-panel tbody tr:last-child td:nth-child(3) input").val(b);
});
- đã thử nghiệm trên Magento 2.2.2
Bài viết chi tiết - https://tutes.in/how-to-manage-magento-2-product-attribution-values-options-USE-console/