11

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.

  • After creating the block you can rearrange position of the block from : site_name/admin/structure/block – Crazyrubixfan Aug 31 '16 at 12:25
  • I assume you mistyped "assign a block to a region". – cilefen Aug 31 '16 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 '16 at 17:32
  • @ShawnConn thanks, that's similar, but not exactly the same. I've found the answer somewhere else. – jmzea Sep 1 '16 at 11:23
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();
  • 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 – Mudassar Ali Jul 14 '16 at 9:15
  • Ask this as another question. Comments aren't for asking questions. – Shawn Conn Jul 14 '16 at 15:35
  • its already there. drupal.stackexchange.com/questions/207042/… – Mudassar Ali Jul 14 '16 at 15:54
  • Whats the id here ? is it same as the block name ? – Crazyrubixfan Mar 10 '17 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. – Parag Apr 12 '17 at 0:08
7

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') }}
  • The problem with this solution is that twig tweaks still requires you to place the block and then 'disable' it. – lexicant Jan 18 '18 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
    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 '16 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 '16 at 8:43
  • Felix Eve has the best answer. It is not crazy complex. – kratos Aug 16 '16 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 '17 at 12:45
4

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

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();
  • This was precisely what I was looking for Thanks, @jmzea! – Beau May 25 '18 at 21:07
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, privacy policy and cookie policy

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