In Magento 2, there are 6 types of products by default: simple, configurable, virtual, downloadable, bundle, and grouped products, and they deliver various unique features and options that common merchants will find sufficient for their websites. However, sometimes we need more than those default options. That is why in this post, we will guide you guys on how to create a new product type and also how to create a new attribute for a product type.

This process has two big steps:

Step 1: Create a new product type

To add a new product type, you just have to create a new file named product_types.xml in the etc folder. The content of the file should be something like this:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Catalog:etc/product_types.xsd">
   <type name="magenest" label="Magenest" modelInstance="Magenest\Product\Model\Product\Type\Magenest" composite="false" isQty="true" canUseQtyDecimals="false" sortOrder="70">
       <customAttributes>
           <attribute name="refundable" value="false"/>
           <attribute name="is_real_product" value="true"/>
       </customAttributes>
   </type>
</config>

Above we are creating a new product type named “Magenest” and have the type id of “magenest”. The custom attributes are of your choice. Now you should create a file at Magenest\Product\Model\Product\Type and have the name “Magenest” with the following content:

<?php


namespace Magenest\Product\Model\Product\Type;


class Magenest extends \Magento\Catalog\Model\Product\Type\AbstractType
{
   const TYPE_ID = 'magenest';

   public function deleteTypeSpecificData(\Magento\Catalog\Model\Product $product){}
}

This is the minimum amount of code that you should implement. In the future, maybe you will need to write some helper methods that you can call on the object of the product of this type.

Done, the above steps should create a new product type for you. If you check the Add new product dropdown, here is what you should see:

One more thing here, if you create a new product of type Magenest but you can’t see where to set the price, weight,... add these lines into your MagenestProductAttribute.php file at Magenest\Product\Setup\Patch\Data

<?php


namespace Magenest\Product\Setup\Patch\Data;
use Magenest\Product\Model\Product\Type\Magenest;
use Magento\Catalog\Model\Product;

class MagenestProductAttribute implements \Magento\Framework\Setup\Patch\DataPatchInterface
{
   private $setup;
   private $eavSetup;

   public function __construct(
       \Magento\Framework\Setup\ModuleDataSetupInterface $setup,
       \Magento\Eav\Setup\EavSetupFactory $eavSetup
   ) {
       $this->setup    = $setup;
       $this->eavSetup = $eavSetup;
   }

   public function apply()
   {
       $eavSetup  = $this->eavSetup->create(['setup' => $this->setup]);
       $fieldList = [
           'price',
           'special_price',
           'special_from_date',
           'special_to_date',
           'minimal_price',
           'cost',
           'tier_price',
           'weight',
       ];
       foreach ($fieldList as $field) {
           $applyTo = explode(',',$eavSetup->getAttribute(Product::ENTITY , $field, 'apply_to'));
           if (!in_array(Magenest::TYPE_ID, $applyTo)) {
               $applyTo[] = Magenest::TYPE_ID;
               $eavSetup->updateAttribute(
                   Product::ENTITY,
                   $field,
                   'apply_to',
                   implode(',', $applyTo)
               );
           }
       }
   }

   public static function getDependencies()
   {
       return [];
   }

   public function getAliases()
   {
       return [];
   }

}

Step 2: Create new attributes

This part should also be no trouble for you. Let's go ahead and create a new file named NewProductAttribute at Magenest\Product\Setup\Patch\Data and add some lines of code:

<?php


namespace Magenest\Product\Setup\Patch\Data;
use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;

class NewProductAttribute implements \Magento\Framework\Setup\Patch\DataPatchInterface
{
   private $setup;
   private $eavSetup;

   public function __construct(
       \Magento\Framework\Setup\ModuleDataSetupInterface $setup,
       \Magento\Eav\Setup\EavSetupFactory $eavSetup
   ) {
       $this->setup    = $setup;
       $this->eavSetup = $eavSetup;
   }

   public function apply()
   {
       $eavSetup  = $this->eavSetup->create(['setup' => $this->setup]);
       $eavSetup->addAttribute(
           \Magento\Catalog\Model\Product::ENTITY,
           'your_attribute_code',
           [
               'group' => 'Product Details',
               'type' => 'varchar',
               'sort_order' => 50,
               'label' => 'Can be wrapped?',
               'input' => 'boolean',
               'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
               'visible' => true,
               'required' => false,
               'user_defined' => false,
               'searchable' => false,
               'filterable' => false,
               'comparable' => false,
               'visible_on_front' => false,
               'used_in_product_listing' => true,
               'unique' => false,
               'apply_to'=>'simple,configurable,bundle,grouped'
           ]
       );
   }

   public static function getDependencies()
   {
       return [];
   }

   public function getAliases()
   {
       return [];
   }
}

This will add a new product attribute in the Product Details group of your backend product detail page. This attribute will be of type varchar and will be displayed as a checkbox since the input is set to Boolean.

Now if you look back, you should see an attribute as follows:

That is how you guys can new product types and new product attributes for the new product types. We at Magenest hope that our article contains the information that you are looking for. Best wishes for you and your business.