I posted a question here, which had one suggestion, but no answer. Does anyone have any advise on how to implement a custom hook in Drupal 8 which will allow other modules to update a table of contents which is created by a parent module? The table of contents will be an unordered list.

  • 3
    Have a look at the section under "To define a hook:" here, does that help?
    – Clive
    Commented May 14, 2016 at 13:13
  • Only partially. This explains how to create a hook for the child function to use, but nothing on how the parent module renders the content. Does the parent use a controller to add content to, say, $output['table_of_contents'] and then the parent's hook appends the data that is returned from the child, to this array? Commented May 14, 2016 at 13:24
  • 2
    @KevinNowaczyk it depends on the purpose of the hook. A hook is not specific for rendering, but can be used for it. If you want to create a custom hook to provide content and you invoke the hook at the place you need the content, it will work. And because the hook is custom and new to your function, you have to define how the hook should provide its results. Then if you invoke the hook during your parent render function you can receive the results in a usable format. Commented May 14, 2016 at 14:15

3 Answers 3


Just for simplicity sake if you want to create and use a custom hook in drupal 8 for other developers to use

first to help others define the use of your hook in mymodule.api.php file this hook can act on anything required.


 // my hook 
 function hook_mymodule_alter_something(array &$data) {
   // here others will make a module that will call this to alter "$data"

then when needed in your module.

 \Drupal::moduleHandler()->invokeAll('mymodule_alter_something', [&$data]);

then the other developer can then make use of this by calling

function MYOTHERMODULE_mymodule_alter_something($data) {

This section resides in a controller in the parent module:

$plugin_items = [];
// Call modules that implement the hook, and let them add items.
\Drupal::moduleHandler()->alter('flot_examples_toc', $plugin_items);
if (count($plugin_items > 0)) {
  $output['plugins'] = [
    '#title' => 'Plugins',
    '#theme' => 'item_list',
    '#items' => $plugin_items,

And this resides in the child [module].module file.

use Drupal\Core\Url;

function mymodule_flot_examples_toc_alter(&$item_list) {
  $options = [
    ':one' => Url::fromRoute('flot_spider_examples.example')->toString(),
  $item_list[] = t('<a href=":one">Spider Chart</a> (with spider plugin)', $options);

The parent creates an array and passes it to the children by reference. They can alter the array by adding elements to it. The parent then adds it to the render array.


You need to implement two hooks 1. hook_token_info() & 2. hook_tokens() in your module file Below i have given code to create my custom token "query-param-all" and used that token in views- Textarea field.....

* Implements hook_token_info().
function mycustom_token_info() {
  $type = [
      'name' => ('Custom Token'),
      'description' => ('Tokens for custom things.'),
  $node['query-param-all'] = [
      'name' => ("Get all URL query string"),
      'description' => ('Get all URL query string'),
  return [
      'types' => ['customtoken' => $type],
      'tokens' => ['customtoken' => $node],

* Implements hook_tokens().
function mycustom_tokens($type, $tokens, array $data, array $options, \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata) {
  $replacements = [];
  //print '<pre>'; print_r($data);exit;
  $current_path = \Drupal::request()->query->all();
  $query_param = '';
  if( count($current_path) > 0) {
    $amper = '';
    $query_param = '?';
    foreach($current_path as $key => $value){
      $query_param .= $amper.$key.'='.$value;
      $amper = '&';

  if ($type == 'customtoken') {
      foreach ($tokens as $name => $original) {
          switch ($name) {
              case 'query-param-all':
                  $replacements[$original] = $query_param;
  return $replacements;
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Apr 6, 2022 at 11:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.