Drupal - Programatically render a block in a twig template

You're on the wrong track with module_invoke(). That's just a fancy way of calling the {$module_name}_block_view() function.

The fact that it changed doesn't matter, the point is that the block system completely changed in 8.x and is now using plugins and config entities, those functions no longer exist.

You have a few options.

a) Re-use an existing block config entity and view it. Very easy, but requires that configuration to exist, e.g. as a disabled block.

$block = \Drupal\block\Entity\Block::load('your_block_id');
$variables['block_output'] = \Drupal::entityTypeManager()
  ->getViewBuilder('block')
  ->view($block);

b) Create the block plugin instance directly, pass it the configuration (you can find the block plugin id and configuration easily in an exported block config entity). The downside is that you don't get render caching, but if you display it somewhere that is already cached (like a node template), that doesn't really matter.

$variables['block_output'] = \Drupal::service('plugin.manager.block')
  ->createInstance($plugin, $configuration)
  ->build();

c) In case of a view, you can also load the view directly and display it.

d) You can also re-think your approach completely and use block regions or Page Manager (which uses standard block plugins in 8.x).


In Drupal 8, this works for rendering a block plugin (that is, one that you've created in a custom module) in a preprocess_hook:

function mymodule_preprocess_something(array &$variables) {
  $customblock = \Drupal::service('plugin.manager.block')->createInstance('my_custom_block', []);
  $variables['content']['custom_block_output'] = $customblock->build();
}

You can then render it in your twig template like this:

{{ content.custom_block_output }}

Note: this will load up a generic version of your block. If you want to load up an instance of your block with variables (after you have created it at /admin/structure/block), you have to load it this way:

    // Load Instance of custom block with variables
    $example_block = \Drupal::entityManager()->getStorage('block')->load('example_block_machine_name');
    if (!empty($example_block)){
      $example_block_content = \Drupal::entityManager()
        ->getViewBuilder('block')
        ->view($example_block);
      if ($example_block_content) {
        // Add block content to build array
        $variables['content']['custom_block_output'] = $example_block_content;
      }
    }

You can use Twig tweak module for that, then you can use the following syntax:

  <dd>{{ drupal_block('myblock') }}</dd>

Related: How do I programmatically place a block?

Tags:

8

Blocks