How to create dropdown select type category attribute programmatically in magento 2?

Magento 2, You can create a custom category attribute with a list of CMS blocks in the dropdown field.

The module is simply residing in the app/code folder of the Magento instance.

For example, We kept the Package name as Rbj and the Module name as CategoryAttribute.
You can keep any name for Packagename/Module name. In our demo, we have kept the Module name as Rbj_CategoryAttribute.

Now start with basic module creation, Registration.php file is to register our module.  Create a registration.php file,

Full Path,  app/code/Rbj/CategoryAttribute/registration.php,

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Rbj_CategoryAttribute',
    __DIR__
);

Create a module.xml file,

Path: app/code/Rbj/CategoryAttribute/etc/module.xml,

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Rbj_CategoryAttribute" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Catalog"/>
        </sequence>
    </module>
</config>

We have added the Magento catalog module as a Sequence in a module.xml file as we have to depend on the Catalog module.

To get all the CMS blocks in a dropdown, we have to call the InstallData.php file.

We have to add attributes using, Magento\Catalog\Model\Category::ENTITY class.

To get the CMS Block option, we need to use “source_model” to define our CMS block collection and iterate through all the cms blocks and set the option value.

Check the definition for the source model inside the InstallData.php file,
‘source’ => ‘Magento\Catalog\Model\Category\Attribute\Source\Page’
In the above Page.php at catalog module, you can check the CMS block collection with label and value option.

Now create InstallData.php file,
app/code/Rbj/CategoryAttribute/Setup/InstallData.php,

<?php
namespace Rbj\CategoryAttribute\Setup;

use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;

class InstallData implements InstallDataInterface
{

    private $eavSetupFactory;

    /**
     * Constructor
     *
     * @param \Magento\Eav\Setup\EavSetupFactory $eavSetupFactory
     */
    public function __construct(EavSetupFactory $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function install(
        ModuleDataSetupInterface $setup,
        ModuleContextInterface $context
    ) {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Category::ENTITY,
            'cms_block_list',
            [
                'type' => 'int',
                'label' => 'Cms Block',
                'input' => 'select',
                'sort_order' => 100,
                'source' => 'Magento\Catalog\Model\Category\Attribute\Source\Page',
                'global' => 2,
                'visible' => true,
                'required' => true,
                'user_defined' => false,
                'default' => null,
                'group' => 'General Information',
                'backend' => ''
            ]
        );
    }
}

category_form.xml used to define our attribute in the Admin Category page. The Magento category page follows the ui_component pattern to display all the category attributes.

Now create a category_form.xml file,
app/code/Rbj/CategoryAttribute/view/adminhtml/ui_component/category_form.xml

<?xml version="1.0" ?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
	<fieldset name="general">
		<field name="cms_block_list">
			<argument name="data" xsi:type="array">
				<item name="options" xsi:type="object">Magento\Catalog\Model\Category\Attribute\Source\Page</item>
				<item name="config" xsi:type="array">
					<item name="required" xsi:type="boolean">true</item>
					<item name="validation" xsi:type="array">
						<item name="required-entry" xsi:type="boolean">true</item>
					</item>
					<item name="sortOrder" xsi:type="number">100</item>
					<item name="dataType" xsi:type="string">string</item>
					<item name="formElement" xsi:type="string">select</item>
					<item name="label" translate="true" xsi:type="string">Cms Block</item>
				</item>
			</argument>
		</field>
	</fieldset>
</form>

We have set up our category attribute in the General Section of the Category page.

Our attribute cms_block_list is a type of select attribute and we have to define our option as Magento\Catalog\Model\Category\Attribute\Source\Page Class.

For installing our module in Magento 2,  We need to run the command using SSH, log in with SSH, and go to your project root path where Magento is installed,  Run the below command,

php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush

The Result:

category attribute cms block option
category attribute cms block