How to Programmatically Create a Block in Drupal 8

Blocks, as the name suggests, are pieces of content that can be placed anywhere on your Drupal site. They can contain simple text, forms or something with complex logic.

In this tutorial, you’ll learn how to create a block using custom code and how to use Drupal Console to generate it. If you’ve used blocks in Drupal 7 then you will be familiar with the new interface in Drupal 8. If you’re a site builder, the whole process of creating, editing and deleting a block is very intuitive.

Before jumping into code, let’s talk about the Drupal Block UI and understand what has changed since Drupal 7.

Block Layout Page

This page will now list only the blocks assigned to a certain region. You’ll notice that a single block can now be assigned to multiple regions and that’s because blocks are now entities.

If you want to assign a block to a region, just click the “Place Block” button and you’ll be presented with an overlay showing all the available blocks.

This page can be accessed by the URL /admin/structure/block

If you want to learn how to create custom block types check out our tutorial: Build a Blog in Drupal 8: Managing Blocks

Create a Block using the Drupal Interface

Like the content page, custom blocks are now listed on a dedicated page, which uses a views to list all the entities of type Block. Use the toolbar menu to access that page: Structure -> Block Layout -> Custom Block Library.

In order to create a new block, click “Add custom block” and select a block type. As mentioned before, Blocks are now fieldable entities (like nodes), that’s why you can see different block types.

This was a big step when compared to Drupal 7 because we could not add new fields to blocks nor use the same block in multiple regions, which was a pain.

Create a Block using Code

Just like the previous version, Drupal 8 also allows us to create blocks using code. With the OOP concepts introduced in this version 8, it’s even more simple and intuitive to use the APIs Drupal provides. So let’s start.

1. Create a module

Go create a folder under “/modules/custom” (you will need to create the ‘custom’ folder), called “my_block_example”.

Inside this folder, create the “.info.yml” file

my_block_example.info.yml

name: My Block Example
type: module
description: Defines a custom block.
core: 8.x
package: WebWash
dependencies:
  - block

Once the folder and file has been created, go enable the module. Please note, Drupal 8 does not require a “.module”.

2. Create a Block Class

In this step, we’ll create a class that will contain the logic of our block. Following the PSR-4 standards, we’ll place our PHP class under /modules/custom/my_block_example/src/Plugin/Block. Create this folder structure and then create a new file called MyBlock.php under it.

The path to the block class should end up being my_block_example/src/Plugin/Block/MyBlock.php.

This file will contain:

  • Annotation meta data, that will allow us to identify the Block. If you want to read more about annotations, check read “Annotations-based plugins” on drupal.org
  • The MyBlock class, containing 4 methods:
build(), blockAccess(), blockForm(), and blockSubmit()

So, let’s create it

<?php

namespace Drupal\my_block_example\Plugin\Block;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;

/**
 * Provides a block with a simple text.
 *
 * @Block(
 *   id = "my_block_example_block",
 *   admin_label = @Translation("My block"),
 * )
 */
class MyBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() {
    return [
      '#markup' => $this->t('This is a simple block!'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  protected function blockAccess(AccountInterface $account) {
    return AccessResult::allowedIfHasPermission($account, 'access content');
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state) {
    $config = $this->getConfiguration();

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    $this->configuration['my_block_settings'] = $form_state->getValue('my_block_settings');
  }
}

If you prefer, grab a copy of the code from GitHub.

That’s it! Your block is created and ready to be used! Just assign the block to a region and you should see it.

Now let’s go through the methods in more detail.

build()

This method will render a renderable array. In our case, we’re returning a basic markup but we could have returned a more complex code, like a form or a views.

The code below demonstrates how to render a form as an example:

/**
 * {@inheritdoc}
 */
public function build() {
  return \Drupal::formBuilder()->getForm('Drupal\my_module\Form\MyBlockForm');
}

blockAccess()

This method allows you to define custom access logic. In our example, any user with the ‘access content’ will see the block.

Notice that we’re calling a method from the AccessResult class here. The static method allowedIfHasPermission will check if the current user (or anonymous) has access to view content (in this case).

blockForm()

This method allows you to define a block configuration form. Let’s suppose we want to render custom text inside this block instead of the static one. All we need to do is to create a form using the Form API and then define whatever fields we need.

blockSubmit()

This is where we save the configuration defined on the previous method.

Create a Block using Drupal Console

If you’re familiar with Drupal Console you already know its power!

Luckily it’s possible to use this tool to create the boilerplate code for custom blocks. Let’s go through the steps, and you should be done in less than one minute.

If you already have Drupal Console installed, follow the steps below, otherwise just follow the instructions on the site to install it.

Generating the block boilerplate code using Drupal Console

Open the terminal and navigate to your Drupal site root folder and run this command:

drupal generate:plugin:block

Select the module you want to create the block under and answer the following questions and you are all set!

Summary

The concept of a block hasn’t really changed, but how they’re implemented has. Code for each block is neatly organized in its own class. Whereas in Drupal 7, all block code was thrown into the “.module” file and got messy quickly.

This code can be found and downloaded from: https://github.com/rafaelferreir4/my_block_example/

Resources

Rafael Nogueira

About Rafael Nogueira

A web lover and enthusiast focused on developing pretty and powerful web-based solutions (mostly Drupal). Acquia Grand Master certified.

Leave a Comment

You have to agree to the comment policy.