Apa cara (resmi) yang tepat untuk secara terprogram menambahkan opsi atribut produk dalam M2? Misalnya untuk manufacturer
atribut produk. Jelas opsi yang ada akan dicocokkan dengan nilai judul "Admin".
32
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 ataseav_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
Buat atribut baru:
Tambahkan opsi khusus.
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 mengharapkanattribute_id
, tetapi tidak ingin bekerja dengannyaattribute_code
.Dalam hal ini kita perlu mendapatkan
attribute_id
dan meneruskannya ke fungsi pembuatan atribut.Maka kita perlu membuat array opsi dengan cara yang diharapkan magento:
Sebagai contoh:
Dan meneruskannya ke fungsi:
sumber
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:
Kemudian dalam fungsi Anda lakukan sesuatu seperti ini:
sumber
$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 untukoption_id
bidang magento internal di ataseav_attribute_option
meja.Untuk Magento 2.3.3 saya menemukan bahwa Anda dapat mengambil pendekatan Magento DevTeam.
Tambahkan atribut dalam fungsi apply ()
sumber
Ini BUKAN jawaban. Hanya solusinya.
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 .
- diuji pada Magento 2.2.2
Artikel terperinci - https://tutes.in/how-to-manage-magento-2-product-attribute-values-options-using-console/
sumber