Blog

Creating a module and adding a product attribute in Magento 2

Warning: This post is from 2015 before Magento 2 was fully released, so some details may be out of date.

The exciting news is that Magento 2 has been released in beta version. And as Magento 2 is new to the eCommerce world, I am new to the C3 Media world. So as part of my introduction to the company, I am throwing myself into learning all things Magento, starting with the latest releases.

A common task when managing a Magento shop is creating a module that programmatically adds new product attributes, so I’ve taken this as an example to investigate. In Magento 2, here’s how we’d create a module:

Create the module file structure

We are first going to need to create the basic file structure that is required for this simple module. We will call this module BrandNewAttr and put it under the C3 namespace (just like Magento 1, every module sits under a vendor’s name – the difference is that Magento 2 uses actual PHP namespaces as introduced to PHP back in v5.3 in 2009). The core, local and community code pools are no more – all module namespaces in Magento 2 go directly in the code folder.

This means we will need to create a folder named C3 in the app/code folder, and then inside that C3 folder create another folder named BrandNewAttr. Inside the BrandNewAttr folder, create an etc folder and a setup folder.

This is the full extent of folders that are required for this module, the reason being that we only need:

  1. A setup script – that will go in the setup folder
  2. A module.xml file – that will go in the etc folder

Register the module and create the module.xml file

We are going to need to tell Magento 2 that our module exists and that it is active. We do this in the app/etc/config.php file by specifying a key value pair containing the name of our module and ‘1’ which represents ‘active’, as follows:

'C3_BrandNewAttr' => 1

Now that Magento 2 knows that our module exists, we have to create the module’s top-level module.xml file (similar to the config.xml file in Magento 1) to set a name and version number for the module. This is the minimum amount of information you can supply in order for Magento to keep track of the latest setup script that has been run (as in Magento 1). The module.xml file should go in the app/code/C3/BrandNewAttr/etc folder and should contain the following code:


 

    

If we hit the front-end of the Magento 2 website in a browser now, a message that says ‘the version number for this module in the database does not match the one it has stored’, will be displayed. The version number is the one displayed in the module.xml file above. You will therefore be prompted to run the bundled bin/magento shell script with the following arguments: bin/magento setup:upgrade. This will write the above setup version number to the database’s setup_module table, irrespective of whether there is a setup script to run.

As we will require a setup script to run later on, once we have our setup script for adding the product attribute, you can simply wait and not run Magento 2’s bin/magento setup:upgrade until the time it is needed. On the other hand if you have direct access to your database and you have previously run the setup script for a test run then you can just remove the module’s row in the setup_module table, then you can run bin/magento setup:upgrade in Magento 2’s root folder. Anyone used to testing setup scripts in Magento 1 will recognise this last step. This is still the quickest way to instruct Magento 2 to rerun your setup scripts.

Creating the setup script known as a ‘class’

Setup scripts are actually classes in Magento 2; if we were creating a table or modifying the structure of an existing table we would create an InstallSchema class, but since we are just adding a product attribute which is stored in EAV tables we will use an InstallData class. With no logic added, the framework of our class will look like this:

eavSetupFactory = $eavSetupFactory;
    }
 
    /**
     * {@inheritdoc}
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
 
    }
}

Besides the constructor, there is only one method that we need to implement: ‘install’. This method provides us with access to the setup object and this is where we will create our product attribute. The EavSetup Factory initialised in the constructor will be used to generate an EavSetup object which will be used to do the following:

eavSetupFactory = $eavSetupFactory;
    }
 
    /**
     * {@inheritdoc}
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        /** @var EavSetup $eavSetup */
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'does_it_look_good?',
            [
                'type' => 'varchar',
                'label' => 'Does it look good?',
                'input' => 'text',
                'required' => false,
                'sort_order' => 3,
                'global' => \Magento\Catalog\Model\Resource\Eav\Attribute::SCOPE_STORE,
                'group' => 'Product Details',
                'used_in_product_listing' => true,
                'visible_on_front' => true
            ]
        );
    }
}

Besides the constructor, there is only one method that we need to implement: ‘install’. This method provides us with access to the setup object and this is where we will create our product attribute. The EavSetup Factory initialised in the constructor will be used to generate an EavSetup object which will be used to do the following:

As you can see, all the addAttribute method requires is:

  • What you wish to add an attribute to
  • The name of the attribute
  • An array of key value pairs denoting the various details of the attribute such as the type, the label, and the group it belongs to

It’s quite possible that you may add an attribute and want to remove it programmatically; maybe because you have simply made a mistake or because it is no longer needed. You can do this by putting the following code inside the install function and re-running the setup script:

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup->removeAttribute(
          \Magento\Catalog\Model\Product::ENTITY,
            'does_it_look_good?');
    }

All done! We can now add information under the attribute

Assuming that you ran your setup script successfully, all that is left to do now is to test that the attribute works. We do this by editing a product and entering some information under the new attribute. Note that by default, if the attribute is equal to null then it will not be listed on the product page.

While the interface looks different to Magento 1, the process of editing a product has not changed:

  1. Go to your admin panel, then Catalog > Products
  2. Click on the product you wish to edit and then enter something under the field you have created
  3. Save the product, clear the cache and then visit the product page on the front end

If you click on the more information tab you should see your attribute listed.

And that’s it. You have created a module and added an attribute! I hope you’ve found this useful. Next up, I will be looking at the process of data migration into Magento 2, so keep an eye out.

About the author

Team C3