Jawaban:
Inilah pendekatan yang saya buat untuk menangani opsi atribut. Kelas pembantu:
<?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;
}
}
Kemudian, baik di kelas yang sama atau termasuk melalui injeksi ketergantungan, Anda dapat menambah atau mendapatkan ID opsi Anda dengan menelepon createOrGetId($attributeCode, $label)
.
Misalnya, jika Anda menyuntikkan My\Module\Helper\Data
sebagai $this->moduleHelper
, maka Anda dapat menghubungi:
$manufacturerId = $this->moduleHelper->createOrGetId('manufacturer', 'ABC Corp');
Jika 'ABC Corp' adalah pabrikan yang ada, itu akan menarik ID. Jika tidak, itu akan menambahkannya.
DIPERBARUI 2016-09-09: Per Ruud N., solusi asli menggunakan CatalogSetup, yang menghasilkan bug yang dimulai pada Magento 2.1. Solusi yang direvisi ini memintas model itu, menciptakan opsi dan label secara eksplisit. Ini harus bekerja di 2.0+.
Magento\Eav\Model\ResourceModel\Entity\Attribute::_processAttributeOptions
. Lihat sendiri, jika Anda menghapus $option->setValue($label);
pernyataan dari kode Anda, itu akan menyimpan opsi, maka ketika Anda mengambilnya Magento akan mengembalikan nilai dari kenaikan otomatis di atas eav_attribute_option
meja.
diuji pada Magento 2.1.3.
Saya tidak menemukan cara yang bisa diterapkan bagaimana cara membuat atribut dengan opsi sekaligus. Jadi pada awalnya kita perlu membuat atribut dan kemudian menambahkan opsi untuk itu.
Suntikkan kelas berikut \ 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,
...
],
);
Fungsi addAttribute
tidak mengembalikan apa pun yang berguna yang dapat digunakan di masa depan. Jadi setelah penciptaan atribut kita perlu mengambil objek atribut sendiri. !!! Penting Kami membutuhkannya karena fungsi hanya mengharapkan attribute_id
, tetapi tidak ingin bekerja dengannya attribute_code
.
Dalam hal ini kita perlu mendapatkan attribute_id
dan meneruskannya ke fungsi pembuatan atribut.
$attributeId = $eavSetup->getAttributeId('catalog_product', 'attribute_code');
Maka kita perlu membuat array opsi dengan cara yang diharapkan magento:
$options = [
'values' => [
'sort_order1' => 'title1',
'sort_order2' => 'title2',
'sort_order3' => 'title3',
],
'attribute_id' => 'some_id',
];
Sebagai contoh:
$options = [
'values' => [
'1' => 'Red',
'2' => 'Yellow',
'3' => 'Green',
],
'attribute_id' => '32',
];
Dan meneruskannya ke fungsi:
$eavSetup->addAttributeOption($options);
Menggunakan kelas Magento \ Eav \ Setup \ EavSetupFactory atau bahkan kelas \ Magento \ Catalog \ Setup \ CategorySetupFactory dapat menyebabkan masalah berikut: https://github.com/magento/magento2/issues/4896 .
Kelas yang harus Anda gunakan:
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;
}
Kemudian dalam fungsi Anda lakukan sesuatu seperti ini:
$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
dan $option
merupakan kelas ORM; Anda tidak harus menyuntikkannya secara langsung. Pendekatan yang tepat adalah menyuntikkan kelas pabrik mereka, lalu membuat instance sesuai kebutuhan. Perhatikan juga Anda tidak menggunakan antarmuka data API secara konsisten.
$option->setValue()
karena itu untuk option_id
bidang magento internal di atas eav_attribute_option
meja.
Untuk Magento 2.3.3 saya menemukan bahwa Anda dapat mengambil pendekatan 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; }
Tambahkan atribut dalam fungsi apply ()
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
]
);
}
Ini mengasumsikan bahwa Anda memiliki akses ke Magento Backend menggunakan browser dan Anda berada di halaman edit atribut (url seperti admin / katalog / product_attribute / edit / attribute_id / XXX / key ..)
Buka Konsol browser (CTRL + SHIFT + J on chrome) dan rekatkan kode berikut setelah mengubah array mimim .
$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);
});
- diuji pada Magento 2.2.2
Artikel terperinci - https://tutes.in/how-to-manage-magento-2-product-attribute-values-options-using-console/