8

Here's my code:

<?php
namespace Demo\Mymodule\Setup;

use Magento\Eav\Setup\EavSetup; 
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Catalog\Setup\CategorySetupFactory;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;


class InstallData implements InstallDataInterface
{
    private $eavSetupFactory;
    private $attributeSetFactory;
    private $attributeSet;
    private $categorySetupFactory;

    public function __construct(EavSetupFactory $eavSetupFactory, AttributeSetFactory $attributeSetFactory, CategorySetupFactory $categorySetupFactory )
        {
            $this->eavSetupFactory = $eavSetupFactory; 
            $this->attributeSetFactory = $attributeSetFactory; 
            $this->categorySetupFactory = $categorySetupFactory; 
        } 

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();

                // CREATE ATTRIBUTE SET 
        $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]);

        $attributeSet = $this->attributeSetFactory->create();
        $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY);
        $attributeSetId = $categorySetup->getDefaultAttributeSetId($entityTypeId);
        $data = [
            'attribute_set_name' => 'NewAttributeSet', 
            'entity_type_id' => $entityTypeId,
            'sort_order' => 200,
        ];
        $attributeSet->setData($data);
        $attributeSet->validate();
        $attributeSet->save();
        $attributeSet->initFromSkeleton($attributeSetId);
        $attributeSet->save();

                // CREATE PRODUCT ATTRIBUTE
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

            $eavSetup->addAttribute(
                    \Magento\Catalog\Model\Product::ENTITY,
                'text_new',
                [
                    'type' => 'varchar',
                    'label' => 'New Text',
                    'backend' => '',
                    'input' => 'text',
                    'wysiwyg_enabled'   => false,
                    'source' => '',
                    'required' => false,
                    'sort_order' => 5,
                    'global' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::SCOPE_STORE,
                    'used_in_product_listing' => true,
                    'visible_on_front' => true,
                    'attribute_set_id' => 'NewAttributeSet',
            ]
        );  

        $setup->endSetup();
    }

} ?>

All working fine but the attribute is assigning to all attribute set and I want on only one attribute set which I have created: NewAttributeSet

1
  • >try to change attribute_set_id to 'attribute_set' Commented Nov 17, 2017 at 7:17

6 Answers 6

14

To prevent Magento 2 from adding your attribute to all attribute sets (as of Magento 2.3.1):

  • You must set 'user_defined' => true, in the array passed to addAttribute().
  • You must not define a group key in the array, otherwise Magento will add your attribute, in the specified group, to all attribute sets.
  • You don't need to define an attribute_set_id key (nor attribute_set). It doesn't do anything.
  • You don't need to specify a sort_order key. It is only used when Magento adds the attribute to all attribute sets.
  • You need to call addAttributeToGroup() after addAttribute() to add it to the attribute set you want.

The code would look like this:

$eavSetup->addAttribute(
    \Magento\Catalog\Model\Product::ENTITY,
    'text_new',
    [
        'user_defined' => true,
        'type' => 'varchar',
        'label' => 'New Text',
        'input' => 'text',
        'required' => false,
        'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
        'used_in_product_listing' => true,
        'visible_on_front' => true,
    ]
);

$eavSetup->addAttributeToGroup(
    \Magento\Catalog\Model\Product::ENTITY,
    'NewAttributeSet',
    'General', // group
    'text_new',
    5 // sort order
);
1
  • Thnx a lot for your post ;) Commented Jan 15, 2021 at 17:26
2

When an attribute gets created with addAttribute() and a group is specified or the attribute should not be a user defined attribute, Magento will add the attribute to all attribute sets with the same entity type (catalog_product). I don't have any clue why, though.

So if you would like to create a non user defined attribute you can first create the attribute as user defined and the change it to not user defined:

$eavSetup->addAttribute(
    \Magento\Catalog\Model\Product::ENTITY,
    'text_new',
    [
                                  // id required, not name of set!
        'attribute_set_id'        => $attributeSet->getAttributeSetId(),
                                  // temporarily!
        'user_defined'            => true,     
                                  // don't yet assign to group!    
        'group'                   => '',

// ----- your other parameters ---------------- 
        'type'                    => 'varchar',
        'label'                   => 'New Text',
        'backend'                 => '',
        'input'                   => 'text',
        'wysiwyg_enabled'         => false,
        'source'                  => '',
        'required'                => false,
        'sort_order'              => 5,
        'global'                  => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::SCOPE_STORE,
        'used_in_product_listing' => true,
        'visible_on_front'        => true,            
    ]
);
$eavSetup->updateAttribute(Product::ENTITY, 'text_new', 'is_user_defined', false);

// Assign attribute now to groups if you need to ...

Note the difference between 'user_defined' and 'is_user_defined' when the attibutes gets created and updated.

Difference between user and non user defined attribute is discussed here.


Implementation of addAttribute() in EavSetup:

public function addAttribute($entityTypeId, $code, array $attr)
{
    $entityTypeId = $this->getEntityTypeId($entityTypeId);

    $data = array_replace(
        ['entity_type_id' => $entityTypeId, 'attribute_code' => $code],
        $this->attributeMapper->map($attr, $entityTypeId)
    );

    $this->_validateAttributeData($data);

    $sortOrder = isset($attr['sort_order']) ? $attr['sort_order'] : null;
    $attributeId = $this->getAttribute($entityTypeId, $code, 'attribute_id');
    if ($attributeId) {
        $this->updateAttribute($entityTypeId, $attributeId, $data, null, $sortOrder);
    } else {
        $this->_insertAttribute($data);
    }

    if (!empty($attr['group']) || empty($attr['user_defined'])) {
        $select = $this->setup->getConnection()->select()->from(
            $this->setup->getTable('eav_attribute_set')
        )->where(
            'entity_type_id = :entity_type_id'
        );
        $sets = $this->setup->getConnection()->fetchAll($select, ['entity_type_id' => $entityTypeId]);
        foreach ($sets as $set) {
            if (!empty($attr['group'])) {
                $this->addAttributeGroup($entityTypeId, $set['attribute_set_id'], $attr['group']);
                $this->addAttributeToSet(
                    $entityTypeId,
                    $set['attribute_set_id'],
                    $attr['group'],
                    $code,
                    $sortOrder
                );
            } else {
                $this->addAttributeToSet(
                    $entityTypeId,
                    $set['attribute_set_id'],
                    $this->_generalGroupName,
                    $code,
                    $sortOrder
                );
            }
        }
    }

    if (isset($attr['option']) && is_array($attr['option'])) {
        $option = $attr['option'];
        $option['attribute_id'] = $this->getAttributeId($entityTypeId, $code);
        $this->addAttributeOption($option);
    }

    return $this;
}
2

Here's working example for Magento 2.3.2:

Use

Magento\Eav\Setup\EavSetup -> $eavSetup

        $eavSetup->addAttribute(
            ProductAttributeInterface::ENTITY_TYPE_CODE,
            'some_cool_product_attribute',
            [
                'user_defined' => true,
                'type' => 'varchar',
                'label' => 'Some cool attribute',
                'input' => 'text',
                'required' => false,
                'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                'used_in_product_listing' => true,
                'visible_on_front' => true,
            ]
        );

Then for example if you want assign this attribute to Default set and Content group you should do:

        $eavSetup->addAttributeToGroup(
            ProductAttributeInterface::ENTITY_TYPE_CODE,
             $eavSetup->getAttributeSetId(ProductAttributeInterface::ENTITY_TYPE_CODE, 'Default'),
            'Content',
            'some_cool_product_attribute',
            5
        );

As result you'll get this attribute in admin: Attribute in admin panel

Attribute in another attribute set

0

Try This One, Check the New Code Added.

<?php
  namespace Demo\Mymodule\Setup;

  use Magento\Eav\Setup\EavSetup; 
  use Magento\Eav\Setup\EavSetupFactory;
  use Magento\Framework\Setup\InstallDataInterface;
  use Magento\Framework\Setup\ModuleContextInterface;
  use Magento\Framework\Setup\ModuleDataSetupInterface;
  use Magento\Catalog\Setup\CategorySetupFactory;
  use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;


  class InstallData implements InstallDataInterface
  {
      private $eavSetupFactory;
      private $attributeSetFactory;
      private $attributeSet;
      private $categorySetupFactory;

      public function __construct(EavSetupFactory $eavSetupFactory, AttributeSetFactory $attributeSetFactory, CategorySetupFactory $categorySetupFactory )
          {
              $this->eavSetupFactory = $eavSetupFactory; 
              $this->attributeSetFactory = $attributeSetFactory; 
              $this->categorySetupFactory = $categorySetupFactory; 
          } 

      public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
      {
          $setup->startSetup();

                  // CREATE ATTRIBUTE SET 
          $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]);

          $attributeSet = $this->attributeSetFactory->create();
          $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY);
          $attributeSetId = $categorySetup->getDefaultAttributeSetId($entityTypeId);
          $data = [
              'attribute_set_name' => 'NewAttributeSet', 
              'entity_type_id' => $entityTypeId,
              'sort_order' => 200,
          ];
          $attributeSet->setData($data);
          $attributeSet->validate();
          $attributeSet->save();
          $attributeSet->initFromSkeleton($attributeSetId);
          $attributeSet->save();

          /*************** New Code Start ***************/
          $attribute_group = 'New Attribute Group Job'; 
          $this->eavSetupFactory->addAttributeGroup(\Magento\Catalog\Model\Product::ENTITY, $attributeSetId, $attribute_group);
          /*************** New Code End ***************/

                  // CREATE PRODUCT ATTRIBUTE
          $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

              $eavSetup->addAttribute(
                      \Magento\Catalog\Model\Product::ENTITY,
                  'text_new',
                  [
                      'type' => 'varchar',
                      'label' => 'New Text',
                      'backend' => '',
                      'input' => 'text',
                      'wysiwyg_enabled'   => false,
                      'source' => '',
                      'required' => false,
                      'sort_order' => 5,
                      'global' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::SCOPE_STORE,
                      'used_in_product_listing' => true,
                      'visible_on_front' => true,
                      'attribute_set_id' => 'NewAttributeSet',
              ]
          );  

          /*************** New Code Start ***************/
          $this->eavSetupFactory->addAttributeToSet(\Magento\Catalog\Model\Product::ENTITY,$attributeSetId,$attribute_group,'text_new',null);
          /*************** New Code End ***************/

          $setup->endSetup();
      }

  } 

  ?>
0

Simply change the below line

'attribute_set_id' => 'NewAttributeSet',

to

'attribute_set' => 'AttributeSetName',

Now your attribute get assigned to above mentioned attribute name.

0

In addition to @sébastien's answer there is actually an exception for user_defined. To set user_defined to false it should be provided with the value "\x00".

This works because the value is checked using empty(), which will return true for the value false, to see if the attribute needs to be added to all attribute sets. The value "\x00", which is a string containing null in hexadecimal, will have empty() return false yet convert to 0 when written to the database.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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