Uncategorized

Concept of Derivatives in Drupal 8

DERIVATIVES

Derivatives provide a simple way to expand a single plugin so that it can represent itself as multiple plugins in the user interface.

USAGE

The role of derivatives comes into the picture in defining multiple blocks when one creates a block programmatically in Drupal8. Using single annotation id multiple blocks cannot be created so to handle such scenarios the concept of derivatives is implemented.

BLOCK CREATION

As we know the creation of custom block involves the definition of annotation which is used to identify the block uniquely.

Below is the code snippet for the custom block in Drupal8:

snippet_1

<?php

/**
 * @file
 * Contains \Drupal\mymodule\Plugin\Block\MyModuleBlock.
 */

namespace Drupal\mymodule\Plugin\Block;
use Drupal\block\BlockBase;

/**
 * Provides a Custom block.
 *
 * @Block(
 *   id = "mymodule_block",
 *   admin_label = @Translation("MyModule block"),
 *   category = @Translation("MyModule")
 * )
 */
class MyModuleBlock extends BlockBase {
  /**
   * Build the content for mymodule block.
   */
  public function build() {
    return array(
      '#markup' => 'Defining Single Block',
    );
  }
}

MULTIPLE BLOCKS DEFINITION

From above code snippet, one can notice that only single block can be defined. In Drupal 8  the build()  function cannot be written twice so there is no obvious way of extending this to support multiple instances of the same block type, that is where derivatives appear in the scene.

Generally, in Drupal 7 blocks are defined in hook_block_info()  which returns an array of block description arrays. So it would have been sufficient to return multiple blocks in an array.

Below are the steps how one can achieve multiple blocks definition

Steps:

  1. Create a folder Derivative under plugin folder of the custom module. Eg: Referring mymodule as a custom module for this blog.Path would be : Drupal/modules/custom/mymodule/src/Plugin/Derivative.
  2. A new class is created called MyModuleBlock and that is saved in path Drupal/modules/custom/mymodule/src/Plugin/Derivative/MyModuleBlock.php. The block will implement DerivativeInterface and  DerivativeBase can be extended.
  3. Implement the interface method getDerivativeDefinitions() . When DerivativeBase is extended  the implementation of getDerivativeDefinition() is not necessary.
  4. Reference the derivative class in the annotation of the block plugin class.
  5. In the block plugin class, use $this->getDerivativeId() wherever you need the actual id of the block instance that is processed.

 

Below code snippet refers snippet_1 with derivatives implemented

<?php

/**
 * @file
 * Contains \Drupal\mymodule\Plugin\Block\MyModuleBlock.
 */

namespace Drupal\mymodule\Plugin\Block;
use Drupal\block\BlockBase;

/**
 * Provides a Custom block.
 *
 * @Block(
 *   id = "mymodule_block",
 *   admin_label = @Translation("MyModule block"),
 *   category = @Translation("MyModule"),
 *   derivative = "Drupal\mymodule\Plugin\Derivative\MyModuleBlock"
 * )
 */
class MyModuleBlock extends BlockBase {
  /**
   * Build the content for mymodule block.
   */
  public function build() {
    $block_id = $this->getDerivativeId();
    return array(
      '#markup' => mymodule_build_block_content($block_id),
    );
  }
}

DEFINITION OF DERIVATIVE CLASS DEFINED IN BLOCK ANNOTATION

We added the derivative class to the annotation and we retrieve the block id to pass it on to a function that retrieves content based on the given argument.

<?php

/**
 * @file
 * Contains \Drupal\mymodule\Plugin\Derivative\MyModuleBlock.
 */

namespace Drupal\mymodule\Plugin\Derivative;
use Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface;

/**
 * Provides block plugin definitions for mymodule blocks.
 *
 * @see \Drupal\mymodule\Plugin\Block\MyModuleBlock
 */
class MyModuleBlock extends DerivativeBase implements ContainerDerivativeInterface {
  /**
   * {@inheritdoc}
   */
  public function getDerivativeDefinitions(array $base_plugin_definition) {
    $myblocks = array(
      'mymodule_block_first' => t('MyModule Block: First'),
      'mymodule_block_second' => t('MyModule Block: Second'),
    );
    foreach ($myblocks as $block_id => $block_label) {
      $this->derivatives[$block_id] = $base_plugin_definition;
      $this->derivatives[$block_id]['admin_label'] = $block_label;
      $this->derivatives[$block_id]['cache'] = DRUPAL_NO_CACHE;
    }
    return $this->derivatives;
  }
}

From the above code snippet, one can observe the  Derivative Class is very similar to the way  hook_block_info() defined in Drupal 7.

Using Derivatives one can differentiate multiple blocks with unique blockid defined as keys in getDerivativeDefinitions.

SUMMARY

In custom block using derivatives, one can achieve multiple block instances and control the block attributes.

 

About The Author

Leave a Reply

*