namespace [Vendor]\[ModuleName]\Setup;

use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class UpgradeData implements UpgradeDataInterface
    protected $eavSetupFactory;

    public function __construct(
        EavSetupFactory $eavSetupFactory
    ) {
        $this->eavSetupFactory = $eavSetupFactory;

    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
        // @todo put attributes here

Everything that follows will go in the // @todo put attributes here bit.

There are a number of entities EAV attributes can be added to; products, categories and customers. We will add a new product attribute so we need this bit of code;

$entityTypeId = $eavSetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY);

We need this because when we make the call to addAttribute() the first parameter is what entity we want to attach the attribute to.

We then need to know specifics about the attribute.

We do that by defining an array of key value pairs defining the attribute.

For example;


$attrs = [
    'author' => [
        'type' => 'text',
        'label' => 'Author',
        'visible_on_front' => true,
        'user_defined' => true,
        'used_in_product_listing' => true,
        'frontend' => '',
        'backend' => '',
        'class' => 'validate-length maximum-length-255',
        'visible' => true,
        'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
        'default' => '',
        'required' => true,
        'searchable' => false,
        'filterable' => true,
        'unique' => false,
        'apply_to' => '',
        'source' => '',
        'group' => 'My Custom Group'

The key ‘author’ is what we will use as the code of the attribute.

I like to set it up so I can define multiple attributes if I need to and then just loop over them adding them one by one.

As you can see there are quite a few things you can define about an attribute. Many can be ommitted if you do not need to change them from the defaults.

Couple of interesting ones though.

class is useful for adding validation rules to your input.

backend is a string path to a class that controls the saving of the attribute. By default this is not required but for a more complex attribute, a multiselect for example, the data needs to be saved differently. In the multiselect case the chosen options need to be imploded together in a string. The class Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend helps do that on save.

If you do specify a backend model, it needs to extend \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend.

If you wish to control more precisely how the attribute is displayed, you would want to make use of frontend. Like backend you would define a string class to be used. The class in this case should extend \Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend

user_defined and group are important because how these are defined determines how the attribute gets added to the existing attribute sets.

Take a look at this piece of code

if (!empty($attr['group']) || empty($attr['user_defined'])) {
    // add attribute to all sets
    // if $attr['group'] is not empty, add it to that group,
    // otherwise add it the default group

You will find the above piece of code in the addAttribute() function of the Magento\Eav\Setup\EavSetup class we are using to add our custom attribute.

I find this quite strange behaviour.

If we wanted to only add it to a specific attribute set we need to not specify a group and tell it that our attribute is user_defined.

We would then have to add the attribute to a group (either manually or programmatically) and an attribute set ourselves.

Probably not an issue.

Oh also, if you don’t specify either it will add it to every attribute set under the general group (General as defined in the EavSetup class).

By the way, if you do specify a group and that group currently doesn’t exist, Magento will create it for you automatically.


See a working code example over at github

  • magento2
  • attributes
  • eav

Like this post? Share it :)

Related Posts