2

I have created a Data patch file to create the product drop down attribute with options. used the following code in it.

<?php
declare(strict_types=1);

namespace Custom\Module\Setup\Patch\Data;

use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

class AddTestAttribute implements DataPatchInterface
{
 private $moduleDataSetup;
 private $eavSetupFactory;
 public $_storeManager;
 private $logger;
 protected $_dir;
 const TYPE_BOOLEAN = "boolean";
 const TYPE_TEXT = "text";
 const TYPE_SELECT = "select";
 protected $_attributeFactory;
 protected $_eavAttribute;
  public function __construct(
    ModuleDataSetupInterface $moduleDataSetup,
    EavSetupFactory $eavSetupFactory,
    \Psr\Log\LoggerInterface $logger,
    \Magento\Store\Model\StoreManagerInterface $storeManager,
    \Magento\Framework\Filesystem\DirectoryList $dir,
    \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attributeFactory,
    \Magento\Eav\Model\Entity\Attribute  $eavAttribute
) {
    $this->moduleDataSetup = $moduleDataSetup;
    $this->eavSetupFactory = $eavSetupFactory;
    $this->_storeManager = $storeManager;
    $this->logger = $logger;  
    $this->_dir = $dir;
    $this->_attributeFactory = $attributeFactory;
    $this->_eavAttribute = $eavAttribute;
}

/**
 * {@inheritdoc}
 */
public function apply()
{
    /** @var EavSetup $eavSetup */
    $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);

    $fileName = 'attributes_data.csv';
    $pubPath = $this->_dir->getPath('pub');
    $attributeFile = $pubPath.'/'.$fileName;
    $arrResult = array();
    if(($handle = fopen($attributeFile, 'r')) !== FALSE) {
        $row = 1;
        while(($data = fgetcsv($handle, 1000000, ',')) !== FALSE) {
            $col_count = count($data);
            $arrResult[] = $data;               
            $row++;
        }
        fclose($handle);
    } 
    $i = 0;
    foreach ($arrResult as $line) {
        if($i > 0){
            $attributeCode = $line[0];                    
            $attributeName = $line[1];
            $inputType = strtolower($line[2]);
            $options = $line[3];
            switch ($inputType) {
                case ($inputType == self::TYPE_BOOLEAN && isset($attributeCode)):  
                    $this->createBooleanAttribute($eavSetup,$attributeCode,$attributeName,$inputType);
                    break;
                case ($inputType == self::TYPE_SELECT && isset($attributeCode)):
                    $this->createSelectAttribute($eavSetup,$attributeCode,$attributeName,$inputType);
                    if(isset($options) && $options != '' ){
                       $optionName = explode (",", $options);
                        if(count($optionName) > 0){
                             $this->createAttributeOptions($eavSetup,$attributeCode,$optionName);
                        } 
                    }


                case ($inputType == self::TYPE_TEXT && isset($attributeCode)):
                    $this->createTextAttribute($eavSetup,$attributeCode,$attributeName,$inputType);
                    break;
                default:
                    $this->createTextAttribute($eavSetup,$attributeCode,$attributeName,$inputType);                    
            }
        }
        $i++;
    } 
}          
/**
 * {@inheritdoc}
 */
public static function getDependencies()
{
    return [];
}

/**
 * {@inheritdoc}
 */
public function getAliases()
{
    return [];
}

public function createSelectAttribute($eavSetup,$attributeCode,$attributeName,$inputType){ //,$options
$this->logger->info('-select Attribute---');
    $type = 'int';
    $eavSetup->addAttribute(
    \Magento\Catalog\Model\Product::ENTITY,
        $attributeCode,
        [
            'type' => $type,
            'group' => 'General',
            'backend' => 'int',
            'frontend' => '',
            'label' => $attributeName,
            'input' => $inputType,
            'class' => '',
            'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Table',
            'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
            'visible' => true,
            'required' => false,
            'user_defined' => true,
            'searchable' => false,
            'filterable' => true,
            "filterable_in_search" => 1,
            'comparable' => false,
            'visible_on_front' => true,
            'used_in_product_listing' => true,
            'unique' => false , 
            'system' => 1                    
        ]
    );
}

public function createTextAttribute($eavSetup,$attributeCode,$attributeName,$inputType){
    $type = 'text';
    $eavSetup->addAttribute(
        \Magento\Catalog\Model\Product::ENTITY,
        $attributeCode,
        [
            'type' => $type,
            'group' => 'Product Details',
            'attribute_set' =>  'Default',
            'label' => $attributeName,
            'backend' => '',
            'input' => $inputType,
            'wysiwyg_enabled'   => false,
            'source' => '',
            'required' => false,
            'sort_order' => 3,
            'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
            'used_in_product_listing' => true,
            'visible_on_front' => true
        ]
    );
}
public function createAttributeOptions($eavSetup,$attributeCode,$optionName){
      $entityType = 'catalog_product';
      $attributeInfo = $this->_eavAttribute->loadByCode($entityType, $attributeCode);

      $attributeId = $attributeInfo->getAttributeId();
      //$attribute_arr = ['aaa','bbb','ccc','ddd'];
      $attribute_arr = $optionName;

      $option = array();
      $option['attribute_id'] = $attributeId;
      foreach($attribute_arr as $key => $value){
          $option['value'][$value][0]=$value;
          foreach($this->_storeManager as $store){
              $option['value'][$value][$store->getId()] = $value;
          }
      }
      if ($option) {
        $eavSetup->addAttributeOption($option);
      }
  }
}

In the above script, I have created a csv file inside pub directory, then reading data from the file and creating the attributes based on the file data.

File content will be like this. enter image description here

In database its created like below.

enter image description here

The problem here is the "drop down" attribute is created well, but the "source_model" is created empty in database also the backend_type created as "text" instead of "int".

Due to this we are unable to see the drop down attribute in layered navigation. Can anyone advise me here please how can i create the drop down attribute with option by reading from the csv file. Thanks!!

5
  • set backend to null (just dont set there anything) Apr 30 '20 at 7:31
  • @KonradSiamro, tried it, but that didn't work. Apr 30 '20 at 7:42
  • anyway You shouldnt set backend like that. Its Backend model, not backend type. Did u tried also to set type to varchar instead of int ? Apr 30 '20 at 7:45
  • Hi. You have received log successfully? When execute datapatch? May 5 '20 at 4:35
  • yes @RohanHapani, logs are working but problem with source model May 5 '20 at 6:11
1

Try like this

            $eavSetup->addAttribute(
                'catalog_product',
                'attribute_code',
                [
                    'group' => 'General',
                    'type' => 'int',
                    'label' => 'My Attribute',
                    'input' => 'select',
                    'required' => false,
                    'visible' => true,
                    'default' => '',
                    'user_defined' => true,
                    'searchable' => true,
                    'filterable' => true,
                    'comparable' => false,
                    'visible_on_front' => true,
                    'used_in_product_listing' => true,
                    'unique' => false,
                    'option' => ['values' => ['Option 1', 'Option 2', 'Option 3']]
                ]
            );
0

Try to replace with this below code :

$eavSetup->addAttribute(
    \Magento\Catalog\Model\Product::ENTITY,
        $attributeCode,
        [
            'group' => 'general',
            'type' => 'int',
            'backend' => '',
            'frontend' => '',
            'label' => 'My Custom Attribute',
            'input' => 'select',
            'note' => 'My Custom Attribute',
            'class' => '',
            'source' => \MyModule\MyDropdownAttribute\Model\Config\Source\Options::class,
            'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
            'visible' => true,
            'required' => false,
            'user_defined' => true,
            'default' => '0',
            'searchable' => false,
            'filterable' => false,
            'comparable' => false,
            'visible_on_front' => true,
            'used_in_product_listing' => true,
            'unique' => false,
            'option' => [ 
                'values' => [],
            ]                   
        ]
    );

Option File :

app/code/MyModule/MyDropdownAttribute/Model/Config/Source/Options.php

<?php 
namespace MyModule\MyDropdownAttribute\Model\Config\Source;

use Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory;
use Magento\Framework\DB\Ddl\Table;

class Options extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
{ 
    /**
     * Get all options
     *
     * @return array
     */
    public function getAllOptions()
    {
        $this->_options = [ 
            ['label'=>'', 'value'=>''],
            ['label'=>'Small', 'value'=>'1'],
            ['label'=>'Medium', 'value'=>'2'],
            ['label'=>'Large', 'value'=>'3']
        ];
        return $this->_options;
    }

    /**
     * Get a text for option value
     *
     * @param string|integer $value
     * @return string|bool
     */
    public function getOptionText($value)
    {
        foreach ($this->getAllOptions() as $option) {
            if ($option['value'] == $value) {
                return $option['label'];
            }
        }
        return false;
    }
}

You need to set your dropdown options files in source attribute. Please replace with this code and check it.

3
  • Thanks Rohan, but where is the code for options here? May 5 '20 at 6:27
  • Please check my updated answer. May 5 '20 at 6:29
  • yes @Rohan, this i got it, but if you look into my question, I am reading option from csv file, how can we map those options here? The answer you posted is to create manually one attribute with options. but in my case i am creating attributes from csv file, there may be n count. May 5 '20 at 6:35
0

Use Below code it will create attribute and import options using csv file

    <?php

public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {


        if (version_compare($context->getVersion(), '1.0.10') < 0) {
            $entityTypeId = $this->eavSetup->getEntityTypeId(Product::ENTITY);
            $options = $this->getCountryOptionsFromCsv('manufacturer-countries-list.csv');
            $this->addNewAttributeWithOptions($entityTypeId, 'custom_attributes_5.csv', $options);
        }




        $setup->endSetup();
    }




 private function addNewAttributeWithOptions($entityTypeId, $fileName, $options)
    {
        $ffcCatalogFixture = 'NameSpace_Catalog::fixtures/'.$fileName;
        $importFile = $this->fixtureManager->getFixture($ffcCatalogFixture);

        if (!$this->filesystem->isExists($importFile)) {
            return;
        }

        $columns = $this->csv->getData($importFile);

        foreach ($columns as $column) {
            //$this->eavSetup->removeAttribute($entityTypeId, $column[self::ATTRIBUTE_CODE]);

            $attributeObj = $this->eavconfig->getAttribute(self::ENTITY_TYPE, self::ATTRIBUTE_CODE);
            $attributeId  =  $attributeObj->getAttributeId();
            if (!$attributeId) {
                if ($column[self::USE_IN_FILTER] == "Yes") {
                    $useInfilter = "true";
                } else {
                    $useInfilter = "false";
                }

                $usedInProductListing = ($column[self::USED_IN_PRODUCT_LISTING] == "Yes") ? true : false;

                $this->eavSetup->addAttribute(
                    Product::ENTITY,
                    $column[self::ATTRIBUTE_CODE],
                    [
                        'global'                  => ScopedAttributeInterface::SCOPE_STORE,
                        'attribute_code'          => $column[self::ATTRIBUTE_CODE],
                        'label'                   => $column[self::ATTRIBUTE_LABEL],
                        'attribute_model'         => '',
                        'backend'                 => $column[self::ATTRIBUTE_BACKEND],
                        'source'                  => $column[self::ATTRIBUTE_SOURCE],
                        'frontend'                => '',
                        'frontend_class'          => $column[self::FRONTEND_CLASS],
                        'type'                    => $column[self::ATTRIBUTE_TYPE],
                        'input'                   => $column[self::ATTRIBUTE_INPUT],
                        'visible'                 => true,
                        'required'                => false,
                        'user_defined'            => true,
                        'searchable'              => false,
                        'filterable'              => $useInfilter,
                        'comparable'              => false,
                        'visible_on_front'        => false,
                        'used_in_product_listing' => $usedInProductListing,
                        'unique'                  => false,
                        'option' => [
                            'values' => $options,
                        ],
                    ]
                );

                // Save the attributes in attribute sets and groups.
                $attributeSets = explode(',', $column[self::ATTRIBUTE_SET]);

                foreach ($attributeSets as $attributeSet) {
                    $this->eavSetup->addAttributeToSet(
                        $entityTypeId,
                        $attributeSet,
                        $column[self::ATTRIBUTE_GROUP],
                        $column[self::ATTRIBUTE_CODE]
                    );
                }
            }
        }
    }
3
  • I am working on Magento 2.3, avoiding using install and upgrade schema. @hitesh May 9 '20 at 16:37
  • okay Please let me know if you want to import options in database so later u can manage it from admin , or you want to put as hardcoded? May 10 '20 at 6:00
  • need to read from csv and create it, please check my question,I have posted neatly, @hitesh May 10 '20 at 10:55

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.