二/090
深入分析drupal的钩子机制
在drupal开发时,大部分时间我们的工作都是在自己开发的模块中实现各种drupal内置的钩子函数,以用来在合适的时间,执行相应的操作。所谓合适的时间大体分为表单渲染前或后,写入数据库前或后等等。现在我们通过userpoint模块的参数配置功能来看看drupal的钩子机制是如何实现的。
在userpoints_admin_settings这个函数中,我们可以看到定义了很多表单元素用来设置userpoints模块相关功能,那如果我们想定义自己的关于用户积分的模块呢?设置要单独分开吗?还是有别的办法,可以将这些本来就有的设置和我们后来开发的设置放置到一起,方便用户操作和管理。这个函数里面有这么一行语句: $form['setting'] = module_invoke_all(’userpoints’, ’setting’);
我们先来看看module_invoke_all这个函数的实现过程。在drupal5.x中:
function module_invoke_all() { $args = func_get_args(); // 取得所有参数列表数组 $hook = array_shift($args); // 钩子名称,也就是第一个参数,移除后返回给hook变量。 $return = array(); foreach (module_implements($hook) as $module) { $function = $module .'_'. $hook; $result = call_user_func_array($function, $args); if (isset($result) && is_array($result)) { $return = array_merge($return, $result); } else if (isset($result)) { $return[] = $result; } }
return $return;}?>
可以看出,第一个参数是指定所有实现了该钩子的模块函数,后面的参数则用来区分情况,类似很多函数的op参数。
接下来看在另外一个模块(userpoints_basepoints)中:
function userpoints_basepoints_userpoints($op, $points = 0, $uid = 0, $event = ”) {
switch ($op) {
case ’setting’:
if (user_access(USERPOINTS_BASEPOINTS_PERM)) {
$group = ‘basepoints’;
$form[$group] = array(
‘#type’ => ‘fieldset’,
‘#collapsible’ => TRUE,
‘#collapsed’ => TRUE,
‘#title’ => t(’!Points for basicpoints’, userpoints_translation()),
);
$form[$group][USERPOINTS_BASEPOINTS] = array(
‘#type’ => ‘textarea’,
‘#title’ => t("enter the amount of one user’s base points when he registed."),
‘#default_value’ => variable_get(USERPOINTS_BASEPOINTS, 0),
);
return $form;
}
}
}
他使用了‘userpoints’这个钩子,第一个op值位setting。也就是说这个模块启用后,实现了userpoints这个钩子的“setting”这个op,那么这里面的表单元素将会显示在userpoints模块设置那部分。
不知道我说明白了没有,总之drupal的钩子机制就是:我们在系统中查找所有实现该钩子的函数,并通过相应的参数判断是否该执行该操作,如果实现,则调用。