Introduction

In the [How to Create Cms Page Programmatically Using DataPatch] chapter I explained why we should use DataPatch in the Magento 2.

To create CMS-Block we laso will use DataPatch. It will save our time in the future.

Solution

<?php

namespace Vendor\ModuleName\Setup\Patch\Data;

use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\Patch\PatchRevertableInterface;
use Magento\Cms\Model\BlockFactory;

class CreateCmsBlock implements DataPatchInterface, PatchRevertableInterface
{
    /**
     * @var BlockFactory
     */
    protected BlockFactory $blockFactory;

    /**
     * @param BlockFactory $blockFactory
     */
    public function __construct(
        BlockFactory $blockFactory
    ) {
        $this->blockFactory = $blockFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function apply()
    {
        $blockData = [
            'title' => 'Test CMS Block',
            'identifier' => 'test_cms_block_identifier',
            'content' => 'Yau! It\'s a test CMS-Block!',
            'stores' => [0],
            'is_active' => 1,
        ];

        $block = $this->blockFactory->create();

        $block->setData($blockData);
        
        $block->save();
    }

    /**
     * {@inheritdoc}
     */
    public static function getDependencies()
    {
        /**
         * No dependencies for this
         */
        return [];
    }

    /**
     * Delete block
     */
    public function revert()
    {}

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

Explanation

First. We prepare an array with the necessary block data like title, identifier, stores on which block will be assigned, and content of the block of course. And don’t forget to set the block is_active = 1.

$blockData = [
    'title' => 'Test CMS Block',
    'identifier' => 'test_cms_block_identifier',
    'content' => 'Yau! It\'s a test CMS-Block!',
    'stores' => [0],
    'is_active' => 1,
];

Important! If you set stores to [0] or you will not use stores in the data array - the block will be assigned to All StoreViews. And if you want to assign the block to Specific StoreView(s), please set necesssary storeview id(s) like

'stores' => [1, 2],

Then we create CMS-Block object:

$block = $this->blockFactory->create();

Now we only need to put $blockData into the $block object and save it.

$block->setData($blockData);
        
$block->save();

Have a nice day 🏝️