10

Using module_invoke_all('some_hook') is easy, but is this better for performance?

foreach (module_implements('some_hook') as $module) {
  $data = module_invoke($module, 'some_hook');
}
11

There is little difference; module_invoke_all() runs the following code:

function module_invoke_all() {
  $args = func_get_args();
  $hook = $args[0];
  unset($args[0]);
  $return = array();
  foreach (module_implements($hook) as $module) {
    $function = $module . '_' . $hook;
    if (function_exists($function)) {
      $result = call_user_func_array($function, $args);
      if (isset($result) && is_array($result)) {
        $return = array_merge_recursive($return, $result);
      }
      elseif (isset($result)) {
        $return[] = $result;
      }
    }
  }

  return $return;
}

The only difference is that with module_invoke_all(), for example, func_get_args() is invoked only once, while when using module_invoke() func_get_args() is called each time module_invoke() is called; that is a marginal difference, though.
There are a few cases where module_implementing() and module_invoke() are used, normally when a module needs to know which module is invoked, such as in the case of search_get_info() that builds an array of information about the modules implementing search functions.

function search_get_info($all = FALSE) {
  $search_hooks = &drupal_static(__FUNCTION__);

  if (!isset($search_hooks)) {
    foreach (module_implements('search_info') as $module) {
      $search_hooks[$module] = call_user_func($module . '_search_info');
      // Use module name as the default value.
      $search_hooks[$module] += array(
        'title' => $module,
        'path' => $module,
      );
      // Include the module name itself in the array.
      $search_hooks[$module]['module'] = $module;
    }
  }

  if ($all) {
    return $search_hooks;
  }

  $active = variable_get('search_active_modules', array('node', 'user'));
  return array_intersect_key($search_hooks, array_flip($active));
}

Another example is image_styles(), which gets the list of all the image styles implemented by the modules, and that uses the following code:

  foreach (module_implements('image_default_styles') as $module) {
    $module_styles = module_invoke($module, 'image_default_styles');
    foreach ($module_styles as $style_name => $style) {
      $style['name'] = $style_name;
      $style['module'] = $module;
      $style['storage'] = IMAGE_STORAGE_DEFAULT;
      foreach ($style['effects'] as $key => $effect) {
        $definition = image_effect_definition_load($effect['name']);
        $effect = array_merge($definition, $effect);
        $style['effects'][$key] = $effect;
      }
      $styles[$style_name] = $style;
    }
  }

In both the cases, the retrieved information is put in an array where the index is the short name of the module.

5

When you have a look at the code, module_invoke_all does just that, plus a couple of sanity checks. And it is easy. :-)

1
-1

It's probably better to use neither, and instead use drupal_alter().

As stated in the module_invoke_all() documentation,

All arguments are passed by value. Use drupal_alter() if you need to pass arguments by reference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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