What changed in the way to implement a block? The documentation for Drupal 8 lists the following hooks as the ones necessary to implement a block.


hook_block_access() controls which users have access to a block
hook_block_view_alter() is used to alter how a block implemented by other modules is rendered
hook_block_view_BASE_BLOCK_ID_alter() is a specialization of the previous hook, similarly to what hook_form_FORM_ID_alter() is for hook_form_alter()


What I don't find is hook_block_info(), which in Drupal 7 allowed to expose the blocks defined from modules, and hook_block_view(), which was invoked when a block defined from a module was rendered in a page.

How do modules expose blocks, in Drupal 8? How are the blocks rendered?
Using the "Powered by Drupal" block as an example:

Drupal 7

modules/system/system.module

/**
 * Implements hook_block_info().
 */
function system_block_info() {
  $blocks['powered-by'] = array(
    'info' =&gt; t('Powered by Drupal'),
    'weight' =&gt; '10',
    'cache' =&gt; DRUPAL_NO_CACHE,
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function system_block_view($delta = '') {
  $block = array();
  switch ($delta) {
    case 'powered-by':
      $block['subject'] = NULL;
      $block['content'] = theme('system_powered_by');
      return $block;
  }
}


Drupal 8

core/modules/system/src/Plugin/Block/SystemPoweredByBlock.php

&lt;?php

/**
 * @file
 * Contains \Drupal\system\Plugin\Block\SystemPoweredByBlock.
 */

namespace Drupal\system\Plugin\Block;

use Drupal\block\BlockBase;
use Drupal\Component\Annotation\Plugin;
use Drupal\Core\Annotation\Translation;

/**
 * Provides a 'Powered by Drupal' block.
 *
 * @Plugin(
 *   id = "system_powered_by_block",
 *   admin_label = @Translation("Powered by Drupal"),
 *   module = "system"
 * )
 */
class SystemPoweredByBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    return array(
      '#children' =&gt; theme('system_powered_by'),
    );
  }
}


The hook_block_info() is replaced by an annotation, containing all of the necessary metadata within the @Plugin portion of the docblock. hook_block_view() is replaced by the BlockPluginInterface::build() method.

The directory structure is the key here. All blocks must be placed into a specific directory within their module folder (src/Plugin/Block).