10

From UI you can add a block in a region in that way:

  1. Go to Admin -> Structure -> Block layout (/admin/structure/block).
  2. Click on "Place block" button besides the region name.

I want to do the same thing but programmatically. How do I add an existing block to a region and save it? This block should then be displayed in that region and be available in the Block layout page.

4
  • After creating the block you can rearrange position of the block from : site_name/admin/structure/block
    – KTM
    Aug 31, 2016 at 12:25
  • I assume you mistyped "assign a block to a region".
    – cilefen
    Aug 31, 2016 at 15:33
  • @IcecreamJelly what I'm trying to do it's to do this programmatically. cilefen, yes that it's what I mean %-)
    – jmzea
    Aug 31, 2016 at 17:32
  • @ShawnConn thanks, that's similar, but not exactly the same. I've found the answer somewhere else.
    – jmzea
    Sep 1, 2016 at 11:23

6 Answers 6

9

To provide a plugin block you can build an array of settings and pass it off to \Drupal\block\Entity\Block::create() to create the Block object and save the instance.

For example if you wanted to add a Devel Execute PHP block to the Seven theme:

$values = array(
  // A unique ID for the block instance.
  'id' => 'devel_execute_php_1',
  // The plugin block id as defined in the class.
  'plugin' => 'devel_execute_php',
  // The machine name of the theme region.
  'region' => 'content',
  'settings' => array(
    'label' => 'Execute PHP',
  ),
  // The machine name of the theme.  
  'theme' => 'seven',
  'visibility' => array(),
  'weight' => 100,
);
$block = \Drupal\block\Entity\Block::create($values);
$block->save();
6
  • Hi, I need help. I have created a custom block using UI and want to place in footer region programatically for testing purpose. I don't know how to get plugin from custom blocks created by UI.. thanks Jul 14, 2016 at 9:15
  • Ask this as another question. Comments aren't for asking questions.
    – Shawn Conn
    Jul 14, 2016 at 15:35
  • its already there. drupal.stackexchange.com/questions/207042/… Jul 14, 2016 at 15:54
  • Whats the id here ? is it same as the block name ?
    – KTM
    Mar 10, 2017 at 10:33
  • @RubberDuckIsKing I believe you can name the id anything you want as long as it is unique. For example, you might want to start it with the name of the module its in.
    – pmagunia
    Apr 12, 2017 at 0:08
8

You ca use Twig tweak module:

Twig Tweak module provides a Twig extension with some useful functions and filters that can improve developer experience.

And then on your twig template region:

{{ drupal_block('block_id') }}
1
  • The problem with this solution is that twig tweaks still requires you to place the block and then 'disable' it.
    – lexicant
    Jan 18, 2018 at 16:49
6

Each instance of a block (which "block type", configuration and the placement) is a config entity: \Drupal\block\Entity\Block. So all you have to do is to create a new instance of this entity with the correct details and you're done.

This can be done but is crazy complex, you would need to understand the plugin system, block plugin system and a lot more.

You can take a look at \Drupal\block\BlockForm::submitForm to get a feel for this or \Drupal\simpletest\BlockCreationTrait::placeBlock. You might want to think about if this is something you really need, the visibility of the block is pretty complex.

4
  • 4
    Apart maybe from visibility conditions, I don't think it's that complicated. \Drupal\simpletest\BlockCreationTrait::placeBlock() is probably a better example to look at, you can also just import some exported configuration files.
    – Berdir
    Apr 5, 2016 at 18:30
  • @Berdir Thanks for the link to the test trait, added it. Since Drupal 8 is still so young, a lot of people don't know a lot about the plugin system and the documentation could use more use cases etc, which can give a lot of devs a hard time working with it.
    – googletorp
    Apr 6, 2016 at 8:43
  • Felix Eve has the best answer. It is not crazy complex.
    – kratos
    Aug 16, 2016 at 3:39
  • @kratos The answer Felix has provided isn't actually solving the question of how to place a block "programmatically", but instead uses config files. Config can only be imported via through drush, config synchronization interface or module installation. If it needs to happen, during runtime, fx post save of a section frontpage node type etc, it would be useless to use this strategy :)
    – googletorp
    Feb 13, 2017 at 12:45
6

I found the answer thanks to How to manipulate an Entity:Block programmatically in Drupal 8.

use Drupal\block\Entity\Block;

$block = Block::load('sitebranding');
$block->setRegion('content');
$block->save();
1
  • This was precisely what I was looking for Thanks, @jmzea!
    – Beau
    May 25, 2018 at 21:07
5

I'm just learning D8 but I seem to have found a much easier way to place a block programmatically (It seemed pretty intimidating after reading googletorp's answer!)

When I enabled my custom module that defined the block I wanted the block to automatically be placed in the correct region. Steps I used to achieve this are:

  1. Enable the module and place the block using the UI at /admin/structure/block
  2. Go to the Single Item config export page at admin/config/development/configuration/single/export
  3. Select Configuration type block and for the Configuration name select the block that you just placed using the UI and then copy the generated code.
  4. In your module create the folder /config/install/
  5. Under the generated code textarea it tells you the filename you need to use. Create this file in the /config/install directory and copy the code in there.
  6. Now when you uninstall your module and then re-enable it the block will automatically be placed.
3
2

The example above is close enough but still not correct. The idea is that you have to come up with your own id of the block instance (in my case devel_execute_php_1112 (maybe because I tried to make it work 1112 times, it will remain mystery)) and then the actual block id (the one that is declared for the custom blocks in the annotation) and the theme. Then just set the region and you are good to go. Created an instance of a block under the desired region.

$blockEntityManager = \Drupal::service('entity.manager')->getStorage('block');
$block = $blockEntityManager->create(
  array(
      'id'=> 'devel_execute_php_1112',
      'plugin' => 'devel_execute_php',
      'theme' => 'seven'
  )
);
$block->setRegion('content');
$block->save();

edit1: I actually checked later the comment above - and it is right. It is just not clear that the id is something that you have to come up with. As a redemption for my lame comment I will post a solution on how to create a block instance of a custom block entity:

$blockEntityManager = \Drupal::service('entity.manager')->getStorage('block');
$block = $blockEntityManager->create(
  array(
      'id'=> 'ggggggggsssssss',
      'plugin' => 'block_content:79d53b4e-9e60-4f97-befc-101da919bb7a',
      'theme' => 'visitb_he_theme'
  )
);
$block->setRegion('content');

basically the same but for a plugin you write block_content:uuid_of_custom_block_entity_instance

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.