How to create custom product attribute using Data Patch in Magento 2

As per our business solutions or client requirements, we need to create custom product attributes. There are 2 ways to create custom product attributes:

1. From Admin
Admin > Stores > Attributes: Product > Add New Attribute

2. Programmatically
We can create custom product attributes using the InstallData setup script as well as using Data Patch. After the release of Magento version 2.3, a data patch is a standard approach to managing database modifications. Using data patch we don’t need to manage setup_version in etc/module.xml. So in this blog, we cover the concept of creating custom product attributes using Data Patch with full code. In the following example, we are creating two types of product attributes: Text and Yes/No.

Related Blog: How to create custom module in Magento 2

File Path: app/code/Mage2/Demo/Setup/Patch/Data/AddTextProductAttribute.php

<?php

declare(strict_types=1);

namespace Mage2\Demo\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;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Type;
use Psr\Log\LoggerInterface;

class AddTextProductAttribute implements DataPatchInterface
{
    /**
     * @var ModuleDataSetupInterface
     */
    private ModuleDataSetupInterface $moduleDataSetup;

    /**
     * @var EavSetupFactory
     */
    private EavSetupFactory $eavSetupFactory;

    /**
     * @var LoggerInterface
     */
    private LoggerInterface $logger;

    /**
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param EavSetupFactory $eavSetupFactory
     * @param LoggerInterface $logger
     */
    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        EavSetupFactory $eavSetupFactory,
        LoggerInterface $logger
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->eavSetupFactory = $eavSetupFactory;
        $this->logger = $logger;
    }

    /**
     * @return void
     */
    public function apply()
    {
        try {
            $productTypes = implode(',', [Type::TYPE_SIMPLE, Type::TYPE_VIRTUAL]);

            /** @var EavSetup $eavSetup */
            $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);

            $eavSetup->addAttribute(Product::ENTITY, 'sample_yes_no', [
                'type' => 'int',
                'backend' => '',
                'frontend' => '',
                'label' => 'Sample Yes/No',
                'input' => 'boolean',
                'class' => '',
                'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
                'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
                'visible' => true,
                'required' => false,
                'user_defined' => false,
                'default' => '',
                'searchable' => false,
                'filterable' => false,
                'comparable' => false,
                'visible_on_front' => false,
                'used_in_product_listing' => true,
                'unique' => false,
                'apply_to' => $productTypes
            ]);

            $eavSetup->addAttribute(Product::ENTITY, 'sample_text_attribute', [
                'type' => 'text',
                'backend' => '',
                'frontend' => '',
                'label' => 'Sample Text Attribute',
                'input' => 'text',
                'class' => '',
                'source' => '',
                'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
                'visible' => true,
                'required' => true,
                'user_defined' => false,
                'default' => '',
                'searchable' => false,
                'filterable' => false,
                'comparable' => false,
                'visible_on_front' => false,
                'used_in_product_listing' => true,
                'unique' => false,
                'apply_to' => $productTypes
            ]);

        } catch (\Exception $e) {
            $this->logger->critical($e);
        }
    }

    /**
     * @return array
     */
    public static function getDependencies(): array
    {
        return [];
    }

    /**
     * @return array
     */
    public function getAliases(): array
    {
        return [];
    }
}

In the above example, we have added the $productTypes array variable only for simple and virtual type products, you can add more than that product type. This is a simple example, you can modify the values of any of the parameters of the addAttribute() function as per your need.

Run the following command after creating a data patch:

bin/magento setup:upgrade

Output:


We hope this blog may understandable and useful to you. You can email us at mage2developer@gmail.com if we missed anything or want to add any suggestions. We will respond to you as soon as possible. Happy to help 🙂

Need Further Help? or Questions?

Contact Us

Create your account

chatsimple