Magento2 - प्रोग्रामेटिक रूप से उत्पाद विशेषता विकल्प जोड़ें


32

प्रोग्राम को M2 में उत्पाद विशेषता विकल्प जोड़ने का सही (आधिकारिक) तरीका क्या है? उदाहरण के लिए manufacturerउत्पाद विशेषता। जाहिर है कि मौजूदा विकल्प "एडमिन" शीर्षक मान से मेल खाता होगा।

जवाबों:


55

यहां वह दृष्टिकोण है जो मैं विशेषता विकल्पों को संभालने के लिए आया हूं। सहायक वर्ग:

<?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;
    }
}

फिर, एक ही कक्षा में या इसे निर्भरता इंजेक्शन के माध्यम से शामिल करके, आप कॉल करके अपना विकल्प आईडी जोड़ या प्राप्त कर सकते हैं createOrGetId($attributeCode, $label)

उदाहरण के लिए, यदि आप इंजेक्षन My\Module\Helper\Dataके रूप में $this->moduleHelperहै, तो आप कॉल कर सकते हैं:

$manufacturerId = $this->moduleHelper->createOrGetId('manufacturer', 'ABC Corp');

यदि 'एबीसी कॉर्प' एक मौजूदा निर्माता है, तो यह आईडी खींच देगा। यदि नहीं, तो इसे जोड़ देगा।

अद्यतन 2016-09-09: रूड एन के अनुसार, मूल समाधान कैटलॉगसेटअप का उपयोग करता था, जिसके परिणामस्वरूप मैगेंटो 2.1 में एक बग शुरू हुआ। यह संशोधित समाधान उस मॉडल को बायपास करता है, जिससे विकल्प और लेबल स्पष्ट रूप से बनते हैं। इसे 2.0+ पर काम करना चाहिए।


3
यह आधिकारिक है जैसा कि आप प्राप्त करने जा रहे हैं। सभी लुकअप और ऑप्शन जोड़ने से कोर मैगेंटो के माध्यम से जाना जाता है। मेरी कक्षा उन मुख्य तरीकों के लिए सिर्फ एक आवरण है जो उन्हें उपयोग करना आसान बनाता है।
बजे रयान होर

1
हाय रयान, आपको विकल्प पर मान सेट नहीं करना चाहिए, यह आंतरिक आईडी मैगनेटो का उपयोग करता है और मुझे यह पता चला है कि यदि आप एक प्रमुख मान के साथ स्ट्रिंग मान को सेट करते हैं जैसे '123 abc कॉर्प' के कार्यान्वयन के कारण कुछ गंभीर समस्याएं Magento\Eav\Model\ResourceModel\Entity\Attribute::_processAttributeOptions। अपने लिए देखें, यदि आप $option->setValue($label);अपने कोड से स्टेटमेंट को हटाते हैं, तो यह विकल्प को बचाएगा, तब जब आप इसे प्राप्त करेंगे तो Magento eav_attribute_optionटेबल पर एक ऑटो-इन्क्रीमेंट से मान लौटा देगा ।
क्विकशिफ्टिन

2
अगर मैं इसे फ़ॉरच्यू फ़ंक्शन में जोड़ता हूं, तो दूसरी पुनरावृत्ति में मुझे "मैगेंटो \ ईव \ मॉडल \ एंटिटी \ एट्रीब्यूट" ऑप्शन मैनेजमेन्ट :: सेटऑन्यूवैल्यू () टाइप स्ट्रिंग का होना चाहिए, दी गई वस्तु
जेईएलएलजे

1
हां यह कोड काम नहीं कर रहा है
सौरव

2
@JELLEJ यदि आप समस्या रहित टाइप टाइप कर रहे हैं: तर्क 3 Magento \ Eav \ Model \ Entity \ Attribute \ OptionManagement के लिए पास किया गया :: setOptionValue () प्रकार स्ट्रिंग का होना चाहिए, ऑब्जेक्ट को फ़ॉर्च फ़ंक्शन में दिया गया है, तब $ विकल्प बदलें-> setLabel () $ optionLabel); से $ विकल्प-> सेटलैबेल ($ लेबल); लाइन 102 पर
Nadeem0035

11

Magento 2.1.3 पर परीक्षण किया गया।

मुझे कोई व्यावहारिक तरीका नहीं मिला कि कैसे एक बार में विकल्पों के साथ विशेषता बनाई जा सके। इसलिए शुरू में हमें एक विशेषता बनाने की जरूरत है और फिर इसके लिए विकल्प जोड़ें।

वर्ग \ 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,
        ...
    ],
);

कस्टम विकल्प जोड़ें।

फ़ंक्शन addAttributeकुछ भी उपयोगी नहीं देता है जो भविष्य में उपयोग किया जा सकता है। इसलिए विशेषता निर्माण के बाद हमें अपने आप से विशेषता वस्तु को प्राप्त करने की आवश्यकता है। !!! महत्वपूर्ण हमें इसकी आवश्यकता है क्योंकि फ़ंक्शन केवल अपेक्षा करता है attribute_id, लेकिन इसके साथ काम नहीं करना चाहता attribute_code

उस स्थिति में हमें attribute_idइसे बनाने और इसे पास करने की जरूरत है ताकि इसे बनाने के लिए फंक्शन तैयार किया जा सके।

$attributeId = $eavSetup->getAttributeId('catalog_product', 'attribute_code');

फिर हमें जिस तरह से magento की उम्मीद है, उसमें विकल्प सरणी उत्पन्न करने की आवश्यकता है:

$options = [
        'values' => [
        'sort_order1' => 'title1',
        'sort_order2' => 'title2',
        'sort_order3' => 'title3',
    ],
    'attribute_id' => 'some_id',
];

उदाहरण के रूप में:

$options = [
        'values' => [
        '1' => 'Red',
        '2' => 'Yellow',
        '3' => 'Green',
    ],
    'attribute_id' => '32',
];

और इसे फंक्शन में पास करें:

$eavSetup->addAttributeOption($options);

AddAttribute 3 परम सरणी पैरामीटर [ 'विकल्प'] ले जा सकते हैं
DWils

10

Magento \ Eav \ Setup \ EavSetupFactory या यहाँ तक कि \ Magento \ कैटलॉग \ Setup \ CategorySetupFactory वर्ग का उपयोग करने से निम्न समस्या हो सकती है: https://github.com/magento/magento2/issues/4896

आपको जिन वर्गों का उपयोग करना चाहिए:

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;
 }

फिर अपने फंक्शन में कुछ ऐसा करें:

 $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);

1
धन्यवाद, आप सही हैं। मैंने उसी हिसाब से अपना जवाब अपडेट किया है। ध्यान दें कि $attributeOptionLabelऔर $optionORM वर्ग हैं; आपको उन्हें सीधे इंजेक्ट नहीं करना चाहिए। उचित दृष्टिकोण उनके कारखाने वर्ग को इंजेक्ट करना है, फिर आवश्यकतानुसार एक उदाहरण बनाएं। यह भी ध्यान दें कि आप एपीआई डेटा इंटरफेस का लगातार उपयोग नहीं कर रहे हैं।
बजे रयान होएर

3
हाय @ रुद, रेयान के जवाब पर मेरी टिप्पणी देखें। आप टेबल पर $option->setValue()एक आंतरिक मैगनेटो option_idफ़ील्ड के लिए कॉल नहीं करना चाहते हैं eav_attribute_option
क्विकशिफ्टिन

धन्यवाद। यही मुझे भी पता चला। मेरे उत्तर को उसी के अनुसार संपादित करेंगे।
रुद एन।

0

Magento 2.3.3 के लिए मैंने पाया कि आप 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;
}
  • लागू करें () फ़ंक्शन में विशेषता जोड़ें

    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
            ]
        );
    }
    

उह मैं सिर्फ यह पता लगाता हूं कि मैं इस सवाल को अलग सवाल में जोड़ना चाहता था। मैं बस इसे यहाँ रहूंगा और इस उत्तर के संदर्भ को जोड़ दूंगा। मुझे उम्मीद है कि यह ठीक है। यह आंशिक रूप से इस प्रश्न का उत्तर है :)
एम्बेड 13

-4

यह एक उत्तर नहीं है। बस एक वर्कअराउंड है।

यह मानता है कि आपके पास ब्राउज़र का उपयोग करके Magento Backend तक पहुंच है और आप संपादन विशेषता पृष्ठ पर हैं (url ऐसा लगता है जैसे व्यवस्थापक / कैटलॉग / product_attribute / edit / विशेषता_id / XXX / कुंजी ..)

ब्राउजर कंसोल (क्रोम पर CTRL + SHIFT + J) पर जाएं और ऐरे मिम को बदलने के बाद निम्नलिखित कोड पेस्ट करें ।

$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);
});

- मैगेंटो 2.2.2 पर परीक्षण किया गया

विस्तृत लेख - https://tutes.in/how-to-manage-magento-2-product-attribute-values-options-using-console/


1
यह एक भयानक दीर्घकालिक समाधान है। आप उन चयनकर्ताओं से समान रूप से रहने की उम्मीद नहीं कर सकते। यदि यह वास्तव में अपेक्षा के अनुरूप काम करता है, तो यह सबसे अच्छा है।
डोमडम्ब्रोगिया

@domdambrogia सहमत हैं। यह एक वर्कअराउंड है।
th3pirat3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.