Profile picture for user admin
Daniel Sipos
13 Feb 2013

Every week I intend to play around with a Drupal hook and show you some of the things you can do with it. But it has been rightly pointed out to me that following a post in which I talk about what hooks are, I should write one that explores the way you can declare your own hook. So this is it, ever wondered how to do it?

Last week I mentioned that in Drupal 7 hooks that end with the word alter can generally be used also from the theme side (template.php) not only from individual modules. The reason is that their role is to catch something before gets put on the page and make alterations to it. This occurs via the &$parameters passed through reference.

Other hooks are rather functional and in general can be called only from module files. They are used to tap into the resources of other modules (including core modules) and extend them. For instance, as we will see, you’ll need to use 2 separate hooks to programmatically create a new block.

Since last week we went over hook_username_alter(), I will now show you how a module can declare its own alter type hook - not sure if this is the right way of calling it though. However, the general idea is to learn how you in your module can make it so that other modules can hook into it in order to make alterations. To illustrate this, we need some basic module functionality. I will use the Hello World equivalent of module development: a custom module that creates a block which displays the last 10 Articles on the site. Simple right?

So here is the code for that, I will briefly explain what everything does after:

/*
 * Helper function that returns the last 10 Article nodes.
 */
function demo_get_nodes() {
  $number = 10;
  $query = db_select('node', 'n')
      ->condition('type', 'article')
      ->condition('status', 1)
      ->fields('n', array('nid', 'title', 'created'))
      ->range(0, $number)
      ->orderBy('created', 'DESC');
  $result = $query->execute()->fetchAll();  
  return $result;
}

/*
 * Implements hook_block_info().
 */
function demo_block_info() {
  $blocks['demo'] = array(
    'info' => t('Latest Articles'), 
    'cache' => DRUPAL_NO_CACHE,
  );
  return $blocks;
}
/*
 * Implements hook_block_view().
 */
function demo_block_view($delta = '') {
  $block = array();
  $nodes = demo_get_nodes();
  $items = array();
  foreach ($nodes as $node) {
    $items[] = l($node->title, 'node/' . $node->nid);
  }
  if ($delta == 'demo') {
    $block['subject'] = t('Latest Articles');
    $block['content'] = array(
      '#theme' => 'item_list',
      '#items' => $items,
      '#type' => 'ul',
    );
  }
  return $block;
}

So these three functions are part of a module called demo. This module retrieves the last 10 published Articles on the site and displays their titles with links in a freshly created block. The first function makes the database query. It uses the Drupal 7 database layer to perform it and return the results. Pretty simple function - not a hook.

However, the next two functions are both hooks. The first one (hook_block_info()) taps into the core module Block and declares a new block into the system, by the name demo with an administrative title Latest Articles. The second one (hook_block_view()) actually creates the block and fills it with content. In our case, it takes the retrieved Article nodes and places them in an HTML list to be displayed by the demo block. Each list item contains a node title linking to the node itself. So far, pretty simple.

Now, if you look at the first function, we hard coded the number of Article nodes to retrieve when we said $number = 10. In most cases, you’d make this available for the user in the UI to change - very easy but not the point of this lesson. However, the current situation is also a good example to illustrate the use of an alter hook. We will make it so that this module by itself can only retrieve 10 Article nodes and display them. However, if another module wants more or less Articles, it will implement a hook and change this number to whatever is needed. For the record, also not difficult.

To do this, we use drupal_alter(). With this Drupal specific function we declare a hook name and provide the variable that will become the parameter passed through reference - in our case $number. So, to illustrate, we need to add this right after we assigned the value 10 to the $number variable.

…
function demo_get_nodes() {
  $number = 10;
  drupal_alter('demo_an', $number);
  $query = db_select('node', 'n')
…

So there it is. The drupal_alter() function now records a new hook name called hook_demo_an_alter() - an stands for article number. To me this made sense, you can name it whatever you want.

All your hook names should start with the module name that declares them in order to avoid name collisions.

So if another module wants to change the $number variable, it will implement this hook like so:

function demo2_demo_an_alter(&$number){
  //change the number of Articles to 5
  $number = 5;
}

And as you can see above, another module called demo2 implements this hook. The $number variable is passed through reference so if demo2 assigns to it a value of 5, on the site demo2 is installed, the demo module will only retrieve 5 Article nodes. I chose to use another module to illustrate this, but you can also test your new hook from the same module if you want and it will still work: demo_demo_an_alter(&$number) { }.

Now, this may not be the most perfect example for illustrating how to declare your own hook, but you get the idea. It's best you always consult the Drupal API references as they are truly your best friend when developing for Drupal. And as always, any questions or if my code doesn’t work, drop a line in the comments.

Profile picture for user admin

Daniel Sipos

CEO @ Web Omelette

Danny founded WEBOMELETTE in 2012 as a passion project, mostly writing about Drupal problems he faced day to day, as well as about new technologies and things that he thought other developers would find useful. Now he now manages a team of developers and designers, delivering quality products that make businesses successful.

Contact us

Comments

Add new comment