7.1hook_hook_info

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

Drupal7对钩子函数的缓加载,还是有改进的,Drupal7里面是这样改进的,通过hook_hook_info,我们就可以把多个钩子函数划分成一组,比如组名叫做rules,那么我们就可以把rules相关的钩子实现,都放到mymodule.rules.inc文件中去。这样当,调用rules相关的钩子时,才会加载mymodule.rules.inc文件。不过,不是很多程序员都了解这个机制,就是很多资深的Drupal开发者,也不了解这个机制。比如,Ubercart里面就没有类似的实现,不过我在uc_ctools模块里面,帮助Ubercart实现hook_hook_info钩子。我们来看看我的实现:

/**

 * Implementation of hook_hook_info().

 */

function uc_ctools_hook_info() {

  //Hooks provided by uc_cart

  foreach (array('add_to_cart', 'add_to_cart_data', 'cart_display', 'cart_pane', 'cart_pane_alter', 'checkout_complete', 'checkout_pane', 'checkout_pane_alter', 'update_cart_item') as $hook) {

    $hooks['uc_' . $hook] = array(

      'group' => 'ubercart',

    );

  }

 

  //Hooks provided by uc_file

  foreach (array('download_authorize', 'file_action', 'file_transfer_alter') as $hook) {

    $hooks['uc_' . $hook] = array(

      'group' => 'ubercart',

    );

  }

 

  //Hooks provided by uc_order

  foreach (array('invoice_templates', 'line_item', 'line_item_alter', 'line_item_data_alter', 'order', 'order_actions', 'order_pane', 'order_pane_alter', 'order_product_alter', 'order_product_delete', 'order_product_can_ship', 'order_state') as $hook) {

    $hooks['uc_' . $hook] = array(

      'group' => 'ubercart',

    );

  }

 

  //Hooks provided by uc_product

  foreach (array('alter', 'class', 'default_classes', 'description', 'description_alter', 'models', 'types') as $hook) {

    $hooks['uc_product_' . $hook] = array(

      'group' => 'ubercart',

    );

  }

 

  //Hooks provided by uc_stock

  $hooks['uc_stock_adjusted'] = array(

    'group' => 'ubercart',

  );

 

  //Hooks provided by uc_store

  $hooks['tapir_table_alter'] = array(

    'group' => 'ubercart',

  );

  foreach (array('form_alter', 'message', 'store_status') as $hook) {

    $hooks['uc_' . $hook] = array(

      'group' => 'ubercart',

    );

  }

 

  //Hooks provided by uc_taxes

  $hooks['uc_calculate_tax'] = array(

    'group' => 'ubercart',

  );

 

   //Hooks provided by uc_payment

  foreach (array('payment_entered', 'payment_gateway', 'payment_gateway_alter', 'payment_method', 'payment_method_alter') as $hook) {

    $hooks['uc_' . $hook] = array(

      'group' => 'ubercart',

    );

  }

 

  //Hooks provided by uc_quote

  foreach (array('shipping_method', 'shipping_type') as $hook) {

    $hooks['uc_' . $hook] = array(

      'group' => 'ubercart',

    );

  }

 

  //Hooks provided by uc_shipping

  $hooks['uc_shipment'] = array(

    'group' => 'ubercart',

  );

  return $hooks;

}

我把Ubercart核心自带的钩子,都合并到了ubercart这个组里面了,如果你的模块需要实现Ubercart的钩子函数,只需要将具体实现放到mymodule.ubercart.inc文件里面就可以了。

这样,我们就可以缓加载钩子函数了,这是一个办法,一个折中的办法。如果,你了解这一点的话,当你遇到token相关的钩子实现时,就可以放到mymodule.tokens.inc里面,当遇到rules的钩子实现时,把对应的钩子函数放到mymodule.rules.inc里面。

我也是在接触了Drupal7一年以后,才了解到这个机制。开始我都不明白,为什么可以把rules相关的钩子函数放到mymodule.rules.inc里面,我们来看一下rules的实现:

/**

 * Implementation of hook_hook_info().

 */

function rules_hook_info() {

  foreach(array('plugin_info', 'data_info', 'condition_info', 'action_info', 'event_info', 'file_info', 'evaluator_info', 'data_processor_info') as $hook) {

    $hooks['rules_' . $hook] = array(

      'group' => 'rules',

    );

    $hooks['rules_' . $hook . '_alter'] = array(

      'group' => 'rules',

    );

  }

  $hooks['default_rules_configuration'] = array(

    'group' => 'rules_defaults',

  );

  $hooks['default_rules_configuration_alter'] = array(

    'group' => 'rules_defaults',

  );

  return $hooks;

}

我们看到,这里分成了两个组,一个是rules,一个是rules_defaults。如果进一步了解的话,还是看一看module_invoke_all, module_implements这两个函数,前者调用了后者,而在module_implements函数里面,参看api.drupal.org。里面包含这样的几段代码:

cache_clear_all('hook_info', 'cache_bootstrap');

$hook_info = module_hook_info();

$include_file = isset($hook_info[$hook]['group']) && module_load_include('inc', $module, $module . '.' . $hook_info[$hook]['group']);

if ($group) {

        module_load_include('inc', $module, "$module.$group");

      }

读懂了这里的代码,我们就基本上彻底的了解这个机制。有兴趣的读者可以进一步的读一下module_hook_info这个函数里面的代码。在api.drupal.org上面阅读即可。我原来一直以为token模块实现了钩子hook_hook_info,但是在token模块里面找了又找,就是找不到,后来,发现它的实现放到了system模块里面:

function system_hook_info() {

  $hooks['token_info'] = array(

    'group' => 'tokens',

  );

  $hooks['token_info_alter'] = array(

    'group' => 'tokens',

  );

  $hooks['tokens'] = array(

    'group' => 'tokens',

  );

  $hooks['tokens_alter'] = array(

    'group' => 'tokens',

  );

 

  return $hooks;

}

我就是借鉴了这里的用法,在uc_ctools模块里面,把Ubercart的相关钩子归成了一个组。

hook_hook_info这种方式,部分解决了问题,由于知道的人不多,很多人仍然将相应的钩子实现放到module文件里面。


Drupal版本: