15

I need to add a CMS block via an install/upgrade script. I've already figured out how to add "normal" CMS pages as seen in the script below. But since I can't find any way to add CMS blocks in Magento 2's code, on Google or here, I'm quite jammed.

namespace [Vendor]\[Module]\Setup;

use Magento\Cms\Model\Page;
use Magento\Cms\Model\PageFactory;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;

class UpgradeData implements UpgradeDataInterface
{
    /**
     * Page factory.
     *
     * @var PageFactory
     */
    private $pageFactory;

    /**
     * Init.
     *
     * @param PageFactory $pageFactory
     */
    public function __construct(PageFactory $pageFactory)
    {
        $this->pageFactory = $pageFactory;
    }

    /**
     * Upgrade.
     *
     * @param ModuleDataSetupInterface $setup
     * @param ModuleContextInterface $context
     */
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();

        if (version_compare($context->getVersion(), '0.0.1') < 0) {
            $testPage = [
                'title' => 'Test page title',
                'identifier' => 'test-page',
                'stores' => [0],
                'is_active' => 1,
                'content_heading' => 'Test page heading',
                'content' => 'Test page content',
                'page_layout' => '1column'
            ];

            $this->pageFactory->create()->setData($testPage)->save();
        }

        $setup->endSetup();
    }
}

I understand I don't need all values defined in the $testPage array, so I stripped it down to the following:

$testPage = [
    'title' => 'Test block title',
    'identifier' => 'test-block',
    'stores' => [0],
    'is_active' => 1
    'content' => 'Test block content'
];

Does anyone know what I need to change to make this test page into a test block?

Note: I based my script on the install data script in the Magento 2 CMS module located in vendor/magento/module-cms/Setup/InstallData.php.

2
  • This is not a "CMS Block" but a "CMS Page".. misleading title..
    – OZZIE
    Aug 29, 2016 at 13:51
  • @OZZIE It isn't. If you had read the description you would have known that above code is to add a page indeed, but the question is to change it to a CMS block installer.
    – user42093
    Nov 10, 2016 at 10:14

3 Answers 3

26

add this to the your class:

private $blockFactory;

and make your constructor look like this:

public function __construct(
    PageFactory $pageFactory,
    \Magento\Cms\Model\BlockFactory $blockFactory
  )
{
    $this->pageFactory = $pageFactory;
    $this->blockFactory = $blockFactory;
}

you can even remove the $pageFactory dependency if you don't need it anymore.

Then replace:

$testPage = [
    'title' => 'Test page title',
    'identifier' => 'test-page',
    'stores' => [0],
    'is_active' => 1,
    'content_heading' => 'Test page heading',
    'content' => 'Test page content',
    'page_layout' => '1column'
];

$this->pageFactory->create()->setData($testPage)->save();

with

$testBlock = [
    'title' => 'Test block title',
    'identifier' => 'test-block',
    'stores' => [0],
    'is_active' => 1,
];
$this->blockFactory->create()->setData($testBlock)->save();
5
  • 2
    Something inside me tells me I could have figured that out myself. Nice and easy answer. Thank you very much. PS: I would like to up vote you're answer, but my reputation won't let me.
    – user42093
    Jul 26, 2016 at 12:10
  • Simple but effective. @KeesHak I have upvoted it for you :P
    – 7ochem
    Jul 26, 2016 at 12:15
  • @KeesHak better use Data interface (BlockInterface) and repositories (BlockRepositoryInterface) instead of factories. Jan 11, 2018 at 12:28
  • @VasiliiBurlacu You are right. I wrote this 1.5 years ago when the repositories were not yet finished.
    – Marius
    Jan 11, 2018 at 12:41
  • That's perfect. Thanks! Just tested with 2.3 and works great. Mar 26, 2020 at 15:48
15

You can try the following solution:

Add 2 classes to the constructor:

/**
 * @var \Magento\Cms\Model\BlockFactory
 */
protected $blockFactory;

/**
 * @var \Magento\Cms\Model\BlockRepository
 */
protected $blockRepository;

/**
 * @param PageFactory $resultPageFactory
 * @param \Magento\Cms\Model\BlockFactory $blockFactory
 * @param \Magento\Cms\Model\BlockRepository $blockRepository
 */
public function __construct(
    PageFactory $resultPageFactory,
    \Magento\Cms\Model\BlockFactory $blockFactory,
    \Magento\Cms\Model\BlockRepository $blockRepository
) {
    $this->resultPageFactory = $resultPageFactory;
    $this->blockFactory = $blockFactory;
    $this->blockRepository = $blockRepository;
}

And use them in the following way:

$data = [
    'title' => 'Test block title',
    'identifier' => 'test-block',
    'stores' => ['0'],
    'is_active' => 1,
    'content' => 'Test block content'
];
$newBlock = $this->blockFactory->create(['data' => $data]);
$this->blockRepository->save($newBlock);

The code is working. Here is the result for this block:

enter image description here

2
  • I implemented the block repository functionality as well to save the block. Seems a slightly better practise indeed. Thank you.
    – user42093
    Jul 26, 2016 at 15:14
  • everythings looks good except the store_id part, this should be dynamic and should pick up the default store id from the database. Jan 13, 2021 at 13:53
1

If your module requires upgrade then use UpgradeData.php and follow the below steps.

  1. increase the setup_version in module.xml
  2. Goto Setup directory and create UpgradeData.php
  3. Import its dependencies as follows,

    namespace Vendor\YourModule\Setup;
    
    use Magento\Framework\Setup\UpgradeDataInterface;
    use Magento\Framework\Setup\ModuleContextInterface;
    use Magento\Framework\Setup\ModuleDataSetupInterface;
    use Magento\Cms\Model\BlockFactory;
    
    class UpgradeData implements UpgradeDataInterface {
    
    private $blockFactory;
    
    public function __construct(LoggerInterface $logger, BlockFactory $blockFactory) {
        $this->blockFactory = $blockFactory;
    }
    
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) {
    
        $setup->startSetup();
    
        if (version_compare($context->getVersion(), '1.1.0') < 0) {
            try{
              $staticBlockInfo = [
                        'title' => 'Title of Sample block',
                        'identifier' => 'sample_block',
                        'stores' => ['0'],
                        'is_active' => 1,
                        'content' => 'This is the sample block content'
                      ];
                $this->blockFactory->create()->setData($staticBlockInfo)->save();
            }catch (Exception $e){
                echo $e->getMessage();
            }
         }
    
         $setup->endSetup();
       }
    }
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.