Jaki jest właściwy (oficjalny) sposób na programowe dodanie opcji atrybutu produktu w M2? Np. Dla manufacturer
atrybutu produktu. Oczywiście istniejącej opcji towarzyszyłaby wartość tytułu „Administrator”.
32
Oto zaproponowane przeze mnie podejście do obsługi opcji atrybutów. Klasa pomocnicza:
<?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;
}
}
Następnie, w tej samej klasie lub włączając ją poprzez wstrzyknięcie zależności, możesz dodać lub uzyskać identyfikator opcji, dzwoniąc createOrGetId($attributeCode, $label)
.
Na przykład, jeśli wstrzykniesz My\Module\Helper\Data
jako $this->moduleHelper
, możesz zadzwonić:
$manufacturerId = $this->moduleHelper->createOrGetId('manufacturer', 'ABC Corp');
Jeśli „ABC Corp” jest istniejącym producentem, pobierze identyfikator. Jeśli nie, doda to.
ZAKTUALIZOWANO 09.09.2016: Per Ruud N., oryginalne rozwiązanie wykorzystało CatalogSetup, co spowodowało błąd w Magento 2.1. To zmienione rozwiązanie omija ten model, tworząc wyraźnie opcję i etykietę. Powinno działać na wersji 2.0+.
Magento\Eav\Model\ResourceModel\Entity\Attribute::_processAttributeOptions
. Przekonaj się, jeśli usuniesz$option->setValue($label);
instrukcję ze swojego kodu, zapisze ona opcję, a następnie po jej pobraniu Magento zwróci wartość z automatycznego przyrostu naeav_attribute_option
stole.testowane na Magento 2.1.3.
Nie znalazłem żadnego praktycznego sposobu, jak utworzyć atrybut z opcjami jednocześnie. Tak więc początkowo musimy utworzyć atrybut, a następnie dodać dla niego opcje.
Wstrzyknąć następującą klasę \ Magento \ Eav \ Setup \ EavSetupFactory
Utwórz nowy atrybut:
Dodaj niestandardowe opcje.
Funkcja
addAttribute
nie zwraca niczego przydatnego, z czego można by skorzystać w przyszłości. Po utworzeniu atrybutu musimy sami pobrać obiekt atrybutu. !!! Ważne Potrzebujemy tego, ponieważ funkcja oczekuje tylkoattribute_id
, ale nie chce z nią pracowaćattribute_code
.W takim przypadku musimy go pobrać
attribute_id
i przekazać do funkcji tworzenia atrybutów.Następnie musimy wygenerować tablicę opcji zgodnie z oczekiwaniami magento:
Jako przykład:
I przekaż to do funkcji:
źródło
Korzystanie z Magento \ Eav \ Setup \ EavSetupFactory lub nawet z \ Magento \ Catalog \ Setup \ CategorySetupFactory może prowadzić do następującego problemu: https://github.com/magento/magento2/issues/4896 .
Klasy, których powinieneś użyć:
Następnie w swojej funkcji wykonaj coś takiego:
źródło
$attributeOptionLabel
i$option
są to klasy ORM; nie należy ich wstrzykiwać bezpośrednio. Właściwym podejściem jest wstrzyknięcie klasy fabrycznej, a następnie utworzenie instancji w razie potrzeby. Pamiętaj też, że nie korzystasz konsekwentnie z interfejsów danych API.$option->setValue()
ponieważ dotyczy to wewnętrznegooption_id
pola magento naeav_attribute_option
stole.W przypadku Magento 2.3.3 odkryłem, że możesz zastosować podejście Magento DevTeam.
Dodaj atrybut w funkcji Apply ()
źródło
To NIE jest odpowiedź. Tylko obejście.
Zakłada się, że masz dostęp do Magento Backend za pomocą przeglądarki i jesteś na stronie atrybutu edycji (adres URL wygląda jak admin / catalog / product_attribute / edit / attribute_id / XXX / key ..)
Przejdź do konsoli przeglądarki (CTRL + SHIFT + J na chrome) i wklej następujący kod po zmianie mimim tablicy .
- testowane na Magento 2.2.2
Szczegółowy artykuł - https://tutes.in/how-to-manage-magento-2-product-attribute-values-options-using-console/
źródło