1

I am using below code to get the option Id with an attribute value/label in a custom extension.

/*
* Get attribute id based on option value
*/
protected function getAttributeOptionId($attributeCode, $label)
{
    $productResource = $this->productFactory->create();
    $attribute = $productResource->getAttribute($attributeCode);
    if ($attribute->usesSource()) {
        return $optionId = $attribute->getSource()->getOptionId($label);
    }
}

This works fine in most cases. When I do a call with params color and red it works just fine.

But there is an issue when i call it with for instance size 20. This only happens when there is attribute label/value with id 20. It just returns the first occurrence it finds (20 as a label or as an id).

I did some research and I found out why this is. Below code is the part which returns the id. The second part in the OR condition $option['value'] == $value causes my issue. It looks for a match in the label OR value (which is the id). It just returns the first one found. I looked in the class there is no alternative method without the OR condtion.

/**
* File: /vendor/magento/module-eav/Model/Entity/Attribute/Source/AbstractSource.php
* @param string $value
* @return null|string
*/
public function getOptionId($value)
{
    foreach ($this->getAllOptions() as $option) {
        if (strcasecmp($option['label'], $value) == 0 || $option['value'] == $value) {
            return $option['value'];
        }
    }
    return null;
}

My question is.

What is the best way to solve this? Is there an alternative way to get an id from a attribute label? Or should I rewrite the method? Or maybe extends the class and use a custom method? In any of these cases I would be glad to see an example or a place to start.

2

I hope this help for your custom extension helper.

<?php
namespace Package\Module\Helper;

class Data extends \Magento\Framework\App\Helper\AbstractHelper
{

    protected $scopeConfig;
    protected $_objectManager = null;
    protected $_attributes        = [];
    protected $_eavSetup        = null;


    public function __construct(
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Framework\ObjectManagerInterface $objectmanager
    )
    {
        $this->scopeConfig = $scopeConfig;
        $this->_objectManager = $objectmanager;
    }

    public function getAttribute($_code, $_force = false) 
    {   
        if(!isset($this->_attributes[$_code]) || $_force) {
            $_attribute = $this->_objectManager->get("Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory")->create();
            $this->_attributes[$_code] = $_attribute->loadByCode(\Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE, $_code);
        }

        return $this->_attributes[$_code];
    }

    public function getEavSetup() {
        if(!$this->_eavSetup) {
            $this->_eavSetup = $this->_objectManager->get('Magento\Eav\Setup\EavSetupFactory')->create([
                'setup' => $this->_objectManager->get('Magento\Framework\Setup\ModuleDataSetupInterface')
            ]);
        }
        return $this->_eavSetup;
    }

    public function getAttributeOptionId($_code, $_value) {
        $attribute = $this->getAttribute($_code);   
        if(!$_value || !$attribute || !$attribute->getId()) {
            return ''; 
        }

        $optionId = '';
        $options = $attribute->getSource()->getAllOptions(false);

        if($options && count($options) > 0) {
            foreach($options as $option){
                if(trim(strtolower($option['label'])) ==  strtolower($_value)){
                    $optionId = $option['value'];
                    break;
                }
            }
        }    

        if(!$optionId) {
            $option = [];
            $option['attribute_id'] = $attribute->getAttributeId();
            $option['value']['option'][0] = $_value; 
            $option['value']['option'][1] = $_value; 
            $option['order']['option'] = ''; 
            $this->getEavSetup()->addAttributeOption($option);

            $attribute = $this->getAttribute($_code, true);
            $options = $attribute->getSource()->getAllOptions(false);

            if($options && count($options) > 0) {
                foreach($options as $option){
                    if(trim(strtolower($option['label'])) ==  strtolower($_value)){
                        $optionId = $option['value'];
                        break;
                    }
                }
            } 
        } 
        return $optionId;
    }
}
  • Thanks, good solution! A thing to note for others when they want to use this too; the best practice is to move direct calls of the objectmanager to the constructor and use dependency injection. +1 – Akif Jan 5 at 13:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.