Beginning Drupal Module Development: Hooks 101 | Unleashed Technologies
Loading...


Drupal is a powerful platform you can use to create your website. There are thousands of custom modules available that will help you to make your Drupal site user-friendly and work in harmony with your business' workflows. However, while they provide a very good starting point, most modules need to be modified to adapt to your requirements. Drupal's strength comes from its modular design, based on the concept of hooks. Understanding how to use hooks and when to create your own hooks is one of the first steps in Drupal development.

Hooks are functions that are invoked when events, like a form being submitted or a user logging in, occur on your site. Hooks use the following naming convention: your_module_name_the_hook_name(). For example, if you would like your module named, login_mail, to send an email anytime anyone logs in, you would implement the hook, hook_user_login(), by creating a function called login_mail_user_login(), with the parameters defined in the hook's documentation. With this function you would define what happens after a user logs in to the Drupal site, in our case, send and email.

login_mail.module

/*
 * Implements hook_user_login();
 * Send an email message every time a user logs into Drupal.
 */
function login_mail_user_login(&$edit, $account){
  // Define email message to be sent
  $subject = 'A user logged in!';
  $to = 'chris@example.com';
  $message = $account->name . ' just logged in!';

  // Send email. It may be a better idea to use Drupal_send_mail(). 
  // For this example, PHP's mail function will do just fine.
  mail($to, $subject, $message);
}

 

Creating your own hooks

This is only possible because the user module makes a call to invoke all functions, in all enabled modules, that implement the hook just after Drupal logs in the user. To allow other modules to hook off of your code on certain events, you need to do the same. Creating hooks for other developers to modify your module's workflow without having to hack your code allows other developers to update your module without worrying to much about things breaking. Using the function module_invoke_all('hookname') in your module you will allow other modules to hook off of your code wherever you would like. For example, let's say you would like allow other modules to hook just after the email is sent out in the code above. We would just need to call the module_invoke_all('hookname') function just after we send out our mail.

login_mail.module

//....

  mail($to, $subject, $message);
  
  // Call all functions in other modules that implement hook_login_mail_sent()
  $results = module_invoke_all('login_mail_sent');
}

 

Now, whenever an enabled module implements  hook_login_mail_sent(), It will be called just after the login notification email is sent.

In order to demonstrate this we can create another module which can take advantage of the hook we just created. In a second module, named login_mail_extend we can create a function, login_mail_extend_login_mail_sent(), that will be invoked after the module above sends out an email.

login_mail_extend.module

/*
 * Implements hook_login_mail_sent().
 */
function login_mail_extend_login_mail_sent(){
  
  // Add a log entry. This could be more descriptive, but it serves the purpose of our example
  watchdog('Login Mail','A user just logged in and an email was sent letting someone know about it.');
}

Creating your own alter hooks

Creating hooks that just trigger other functions is all fine and dandy, but what if you would like to give the opportunity for other modules to modify variables before you use them? This is where alter hooks come into play. Alter hooks, named your_module_name_the_hook_name_alter(), allow other modules to modify your variables because the arguments can be passed by reference. To call these hooks we can use the function drupal_alter('the_hook_name', $var1, $var2, $var3) which will allow the $var1, $var2 and $var3 to be modified by other modules, where $var2 and $var3 are optional. The limitation of Drupal alter is that only up to three variables can be passed. For example if we would like to allow other modules to edit the email message before we send it we can call drupal_alter() before the email is sent.

login_mail.module

  //....

  // Allow other modules to alter the message before it is sent
  drupal_alter('login_mail_message', $message);

  // Send email
  mail($to, $subject, $message);

  //....


To demonstrate this, in the login_mail_extend module we created earlier we can implement the hook, hook_login_mail_message_alter(), by creating a function with the signature, login_mail_extend_login_mail_message_alter(&$message). Please note that the $message variable is preceded by an ampersand because the argument is not the $message variable itself, just a reference to the $message. This allows us to alter it and add a signature to the message before it is sent.

login_mail_extend.module

/*
 * Implements hook_login_mail_message_alter().
 */
function login_mail_extend_login_mail_message_alter(&$message){
  // Define the signature
  $signature = "\r\n\r\nSincerely,\r\nMalcolm Reynolds";
  
  // Append the signature to the email message
  $message .= $signature;
}

Conclusion

Developing Drupal modules is highly reliant on the concept of hooks. Being able to implement hooks as well as to prove others with the ability to extend your modules functionality without hacking your code will allow you to take full advantage of Drupal's modular design. In developing many modules I have found that the hook I use most often is hook_form_alter() and is usually a great place to start. Download the completed example modules in this post.