Voici l'approche que j'ai trouvée pour gérer les options d'attribut. Classe d'assistance:
<?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;
}
}
Ensuite, dans la même classe ou en l'incluant via l'injection de dépendances, vous pouvez ajouter ou obtenir votre ID d'option en appelant createOrGetId($attributeCode, $label)
.
Par exemple, si vous injectez en My\Module\Helper\Data
tant que $this->moduleHelper
, vous pouvez appeler:
$manufacturerId = $this->moduleHelper->createOrGetId('manufacturer', 'ABC Corp');
Si «ABC Corp» est un fabricant existant, il extraira l'ID. Sinon, il l'ajoutera.
MISE À JOUR 2016-09-09: Per Ruud N., la solution d'origine a utilisé CatalogSetup, ce qui a entraîné un bogue à partir de Magento 2.1. Cette solution révisée contourne ce modèle, créant l'option et l'étiquette explicitement. Cela devrait fonctionner sur 2.0+.
Magento\Eav\Model\ResourceModel\Entity\Attribute::_processAttributeOptions
. Voyez par vous-même, si vous supprimez l'$option->setValue($label);
instruction de votre code, elle enregistrera l'option, puis lorsque vous la récupérerez, Magento renverra la valeur d'un incrémentation automatique sur laeav_attribute_option
table.testé sur Magento 2.1.3.
Je n'ai trouvé aucun moyen pratique de créer un attribut avec des options à la fois. Donc, au départ, nous devons créer un attribut, puis ajouter des options pour celui-ci.
Injectez la classe suivante \ Magento \ Eav \ Setup \ EavSetupFactory
Créer un nouvel attribut:
Ajoutez des options personnalisées.
La fonction
addAttribute
ne renvoie rien d'utile qui puisse être utilisé à l'avenir. Ainsi, après la création de l'attribut, nous devons récupérer l'objet attribut par nous-mêmes. !!! Important Nous en avons besoin car la fonction attend uniquementattribute_id
, mais ne veut pas travailler avecattribute_code
.Dans ce cas, nous devons l'obtenir
attribute_id
et le transmettre à la fonction de création d'attribut.Ensuite, nous devons générer un tableau d'options de la manière attendue par magento:
Comme exemple:
Et passez-le pour fonctionner:
la source
L'utilisation de la classe Magento \ Eav \ Setup \ EavSetupFactory ou même de la classe \ Magento \ Catalog \ Setup \ CategorySetupFactory peut entraîner le problème suivant: https://github.com/magento/magento2/issues/4896 .
Les classes que vous devez utiliser:
Ensuite, dans votre fonction, faites quelque chose comme ceci:
la source
$attributeOptionLabel
et$option
sont des classes ORM; vous ne devez pas les injecter directement. L'approche appropriée consiste à injecter leur classe d'usine, puis à créer une instance selon les besoins. Notez également que vous n'utilisez pas les interfaces de données API de manière cohérente.$option->setValue()
car c'est pour unoption_id
champ magento interne sur laeav_attribute_option
table.Pour Magento 2.3.3, j'ai constaté que vous pouvez adopter l'approche Magento DevTeam.
Ajouter un attribut dans la fonction apply ()
la source
Ce n'est PAS une réponse. Juste une solution de contournement.
Il suppose que vous avez accès à Magento Backend à l'aide du navigateur et que vous êtes sur la page d'édition d'attribut (l'URL ressemble à admin / catalogue / product_attribute / edit / attribute_id / XXX / key ..)
Accédez à la console du navigateur (CTRL + MAJ + J sur Chrome) et collez le code suivant après avoir modifié le mimim du tableau .
- testé sur Magento 2.2.2
Article détaillé - https://tutes.in/how-to-manage-magento-2-product-attribute-values-options-using-console/
la source