Question

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!!

No correct solution

OTHER TIPS

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

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.

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]
                    );
                }
            }
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top