Drupal 8 API: blocks

Pre-requisites

Controlling the livery of the page via regions and blocks

Outside of the main content—usually, what site maintainers understand as a "page", or "event", or "blogpost"—lies what we might call the livery: the branding, logos, persistent navigation and elements common to large proportions of any website. A key aspect of content management systems is that they work to keep a coherent design of this livery across the entire website: as much as they possibly can. This means using standard templates (which we'll look at later) to determine a lot of the HTML markup, and only permitting certain areas within that markup to change.

Drupal calls these changeable areas regions, and the "chunks" that can be moved around within them, blocks. Here's a suggestion for how raw HTML templates, and configurable regions and blocks, might separate out in your own theme:

Obviously no two themes are the same, but this hopefully indicates how: blocks can sit in regions (and be moved within them, or from region to region); and regions are defined at the theme layer to sit within HTML; which is in turn not particularly configurable, to try to maintain

Each block can contain e.g: a chunk of a menu (potentially long menu hierarchies); widgets to subscribe to a post or a newsletter; even custom content editable within the Drupal admin interface. The editable content of a node is itself inserted as a block of a special type: typically you'll want to leave this untouched, in the main content column; but, by turning that into a block too, Drupal 7 and now 8 are able to make all chunks of content behave and relate to each other in the same way, improving maintainability and consistency.

Defining a custom block in code

Custom blocks live in modules, so you should know already how to create a module in Drupal 8. They're provided by a PHP class which extends a particular subtype of plugins (more on them later.) That means that, if you create a file in the src/Plugin/Block/ subfolder of your module, and if both the class and file have the right naming conventions (as discussed previously), and also methods and comment formatting (more important than you think: see below), then the block your code describes will appear in Drupal's block/region admin UI automatically, with no extra effort.

Here's an example, in a file called TutorialBlock.php, in the module sites/default/modules/d8api/, in a further subfolder src/Plugin/Block/:

<?php
 
namespace Drupal\d8api\Plugin\Block;
 
use Drupal\Core\Block\BlockBase;
 
/**
 * Block for the tutorial.
 *
 * @Block(
 *   id = "d8api_tutorial_block",
 *   admin_label = @Translation("Tutorial block")
 * )
 */
class TutorialBlock extends BlockBase {
 
  /**
   * {@inheritDoc}
   *
   * From BlockPluginInterface via BlockBase.
   */
  public function build() {
    return [
      '#type' => '#markup',
      '#markup' => 'Tutorial block',
    ];
  }
 
}

The necessary elements to this code are:

  • Extend the core BlockBase class, using inheritance so that our new class "looks right" to Drupal, and must provide the relevant methods.
  • Implement the BlockPluginInterface#build() method, which is the one "relevant method" that BlockBase leaves up to us entirely.
  • Format the class comment to use annotations like @Block.

As previously seen during discussions about routing the build() method returns a "render(able) array.html" of data describing what should appear in the block. We'll discuss that later.

Annotations are the Drupal 8 way of providing information that used to be in _info() hooks in Drupal 7: metadata about the classes. We won't discuss them further here, but suffice it to say that they mean that the syntax of a comment becomes important, in the same way as the syntax of your code.

What you should see

First, you probably need to clear cache. This can be done in the admin UI ("Configuration" > "Performance" > "Clear all caches") or using Drush (drush cr).

If you then navigate to "Structure" > "Block layout" and scroll down to any region e.g. "Sidebar left", then when you click on "Place block" you should be able to search for your new block in the modal dialog:

Finally, click back to your homepage, and you should see the new block in place; here, in the bottom of the left sidebar:

Congratulations! you've just created a custom block.

Further reading etc.