Antworten:
Hier ist der Ansatz, den ich für den Umgang mit Attributoptionen entwickelt habe. Hilfsklasse:
<?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;
}
}
Anschließend können Sie Ihre Options-ID entweder in derselben Klasse oder über die Abhängigkeitsinjektion hinzufügen oder durch Aufrufen abrufen createOrGetId($attributeCode, $label)
.
Wenn Sie beispielsweise My\Module\Helper\Data
als injizieren $this->moduleHelper
, können Sie Folgendes aufrufen:
$manufacturerId = $this->moduleHelper->createOrGetId('manufacturer', 'ABC Corp');
Wenn 'ABC Corp' ein bestehender Hersteller ist, wird die ID gezogen. Wenn nicht, wird es hinzugefügt.
AKTUALISIERT 2016-09-09: Per Ruud N., die ursprüngliche Lösung verwendete CatalogSetup, was zu einem Fehler führte, der in Magento 2.1 begann. Diese überarbeitete Lösung umgeht dieses Modell und erstellt die Option und die Bezeichnung explizit. Es sollte auf 2.0+ funktionieren.
Magento\Eav\Model\ResourceModel\Entity\Attribute::_processAttributeOptions
. Sehen Sie selbst, wenn Sie die $option->setValue($label);
Anweisung aus Ihrem Code entfernen , wird die Option gespeichert, und wenn Sie sie abrufen, gibt Magento den Wert von einem automatischen Inkrement in der eav_attribute_option
Tabelle zurück.
Getestet mit Magento 2.1.3.
Ich habe keine praktikable Möglichkeit gefunden, ein Attribut mit Optionen auf einmal zu erstellen. Zunächst müssen wir ein Attribut erstellen und dann Optionen hinzufügen.
Injizieren Sie die folgende Klasse \ 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,
...
],
);
Die Funktion addAttribute
gibt nichts Nützliches zurück, das in Zukunft verwendet werden kann. Nach der Attributerstellung müssen wir das Attributobjekt also selbst abrufen. !!! Wichtig Wir brauchen es, weil die Funktion nur erwartet attribute_id
, aber nicht damit arbeiten will attribute_code
.
In diesem Fall müssen wir sie abrufen attribute_id
und an die Attributerstellungsfunktion übergeben.
$attributeId = $eavSetup->getAttributeId('catalog_product', 'attribute_code');
Dann müssen wir das options array so generieren, wie es von magento erwartet wird:
$options = [
'values' => [
'sort_order1' => 'title1',
'sort_order2' => 'title2',
'sort_order3' => 'title3',
],
'attribute_id' => 'some_id',
];
Zum Beispiel:
$options = [
'values' => [
'1' => 'Red',
'2' => 'Yellow',
'3' => 'Green',
],
'attribute_id' => '32',
];
Und übergeben Sie es an Funktion:
$eavSetup->addAttributeOption($options);
Die Verwendung der Klasse Magento \ Eav \ Setup \ EavSetupFactory oder sogar der Klasse \ Magento \ Catalog \ Setup \ CategorySetupFactory kann zu folgendem Problem führen: https://github.com/magento/magento2/issues/4896 .
Die Klassen, die Sie verwenden sollten:
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;
}
Dann machen Sie in Ihrer Funktion so etwas:
$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
und $option
ORM-Klassen sind; Sie sollten sie nicht direkt injizieren. Der richtige Ansatz besteht darin, die Factory-Klasse zu injizieren und dann nach Bedarf eine Instanz zu erstellen. Beachten Sie auch, dass Sie die API-Datenschnittstellen nicht konsistent verwenden.
$option->setValue()
da dies für ein internes Magento- option_id
Feld in der eav_attribute_option
Tabelle gilt.
Für Magento 2.3.3 habe ich festgestellt, dass Sie den Magento DevTeam-Ansatz verwenden können.
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; }
Attribut in Funktion apply () hinzufügen
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
]
);
}
Es wird davon ausgegangen, dass Sie über einen Browser auf Magento Backend zugreifen können und sich auf der Seite zum Bearbeiten von Attributen befinden (die URL sieht aus wie admin / catalog / product_attribute / edit / attribute_id / XXX / key.)
Wechseln Sie zur Browserkonsole (STRG + UMSCHALT + J in Chrome) und fügen Sie den folgenden Code ein, nachdem Sie den Array-Mimim geändert haben .
$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);
});
- getestet auf Magento 2.2.2
Ausführlicher Artikel - https://tutes.in/how-to-manage-magento-2-product-attribute-values-options-using-console/