Creating custom hooks in Drupal and passing variables by reference

Versions used: 

The cool thing about Drupal is that it adopts a modular approach. This is great because it enables me to override functionality in a controlled way with the use of those hook thingy-ma-jigs you keep hearing about. As a result, it’s harder for me to break something, and also makes life easier when upgrading code.

So what is a hook? A hook is a technique used in Drupal that allows modules to hook into the flow of execution. So rather than editing the code within the Drupal core or Community modules (they call this hacking), you can plug right into it and manipulate/override it from the safety of your own module.

Well that’s just swell, but what if I want to make my own hooks? Creating custom hooks is easy peasy in Drupal with the use of a function called module_invoke_all(). This function searches for any function within a module that match a specific naming pattern. The module_invoke_all() function will return an array of values from any hook implementation. If there are multiple modules, and there are more then one matching hooks, the results are merged.

Basic usage

Simply put module_invoke_all() inside any code:

<?php
$data
= module_invoke_all('example_thingy');
?>

Note: it's good practice to name the hook starting with the name of the module that created it. So in the example above the module name would be example. Now in another module you can invoke the hook by creating a function called MODULENAME_example_thingy, replacing MODULENAME with the name of your module (obviously).

<?php
/**
 * Implements hook_example_thingy().
 */
function MODULENAME_example_thingy() {
  return
'anything you want';
}
?>

Pass Variables

You can pass variables to the hook.

Then just add the arguments.

/**
 * Implements hook_example_thingy().
 */
function MODULENAME_example_thingy($my_var) {
  // now you have access to $my_var
  return 'anything you want';
}

Pass Variables by reference

It would be natural to think you can pass variables by reference by simply adding an ampersand to the argument in the hook function like the below:

/**
 * Implements hook_example_thingy().
 */
function MODULENAME_example_thingy(&$my_var) {
  return 'anything you want';
}

Unfortunately, this does not work. Instead, you need to use drupal_alter() after module_invoke_all().

$my_var = 'some_var';
$data = module_invoke_all('example_thingy', $my_var);
drupal_alter('example_thingy', $my_var);

Now, with the use of the preceeding ampersand, the variable will be passed by reference. Note that the naming of the hook has changed as using drupal_alter() forces the _alter suffix on the hook.

/**
 * Implements hook_example_thingy().
 */
function MODULENAME_example_thingy_alter(&$my_var) {
  // you can now change $my_var directly
}