4.2 钩子

作者:老 葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com

  谈到模块,就不得不提到钩子这个概念。我有时也喜欢把钩子称作钩子机制,我们可以把钩子看做Drupal的内部事件。有时也可以钩子看作是特殊的回调函数。
模块就是通过钩子,与Drupal核心系统无缝整合在一起了。钩子是一个很抽象的概念,我们通过代码来理解一下钩子机制。

function module_invoke_all() {

  $args = func_get_args();

  $hook = $args[0];

  unset($args[0]);

  $return = array();

  foreach (module_implements($hookas $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;

}

 

    代码参考地址:

http://api.drupal.org/api/drupal/includes--module.inc/function/module_invoke_all

    函数module_invoke_all是理解钩子的关键,而这里面,foreach循环中,函数module_implements是理解钩子的又一关键,它用来获取所有实现了钩子$hook的模块。而在这个循环体代码里面,第一句给出了钩子的命名规范。模块在实现钩子的时候,必须采用“模块名_钩子名”形式。其余代码的含义,就是如果这个具体的钩子函数存在(function_exists($function)),那么就调用这个钩子函数(call_user_func_array($function, $args))。

 

    Drupal中的钩子大致可以分为3类,采用module_invoke_all调用的钩子是一类,也是最常见的;采用module_invoke调用的钩子是一类,这种钩子在Drupal核心中经常出现;还有一个就是主题钩子,比如theme_item_list,这里的item_list有时也被称为主题钩子。

 

    上面提到了module_invoke,让我们看一下它的代码:

<?php

function module_invoke() {

  $args = func_get_args();

  $module = $args[0];

  $hook = $args[1];

  unset($args[0], $args[1]);

  if (module_hook($module$hook)) {

    return call_user_func_array($module . '_' . $hook$args);

  }

}

?>

    在这个函数中,call_user_func_array函数只调用了一次,而在前面的module_invoke_all函数的代码中,它被循环调用了多次。这就是两类钩子之间的区别。

    有关钩子的更多信息,可以参看api.drupal.org上的在线文档,http://api.drupal.org/api/drupal/includes--module.inc/group/hooks/7。此外,如果一个模块对外提供了钩子,那么在这个模块的文件夹下面,通常会有一个modulename.api.php这样的文件,里面包含了钩子的具体说明,比如在用户模块下面,就有一个这样的文件user.api.php,里面包含了用户模块对外提供的所有钩子。

 

 


Drupal版本: