Drupal的钩子系统
Drupal的很多功能都是可以定制的。以导航菜单为例,blog模块需要在菜单上添加一些功能,comment模块需要在菜单上添加一些功能,我们开发的自定义模块也需要在菜单上添加一些功能。Drupal开发者为了达到这样的扩展目的,设计了钩子系统,导航菜单就是其中一个名为menu的钩子。有了钩子系统,开发人员就可以在blog模块定义一个钩子函数从而实现menu钩子。Drupal要求钩子函数的命名必须要求以模块名开始,以钩子名为后缀。
function block_menu() {
$items['admin/structure/block/manage/%/%'] = array(
'title' => 'Configure block',
'page callback' => 'drupal_get_form',
'page arguments' => array('block_admin_configure', 4, 5),
'access arguments' => array('administer blocks'),
'file' => 'block.admin.inc',
);
$items['admin/structure/block/manage/%/%/configure'] = array(
'title' => 'Configure block',
'type' => MENU_DEFAULT_LOCAL_TASK,
'context' => MENU_CONTEXT_INLINE,
);
$items['admin/structure/block/manage/%/%/delete'] = array(
'title' => 'Delete block',
'page callback' => 'drupal_get_form',
'page arguments' => array('block_custom_block_delete', 4, 5),
'access arguments' => array('administer blocks'),
'type' => MENU_LOCAL_TASK,
'context' => MENU_CONTEXT_NONE,
'file' => 'block.admin.inc',
);
... ...
return $items;
}
module_hook_info()函数查询所有可以实现的钩子,实质上也是使用的钩子方式:
function module_hook_info() {
$hook_info = array();
foreach (module_list() as $module) {
$function = $module . '_hook_info'; // hook_info钩子
if (function_exists($function)) {
$result = $function();
if (isset($result) && is_array($result)) {
$hook_info = array_merge_recursive($hook_info, $result);
}
}
}
// We can't use drupal_alter() for the same reason as above.
foreach (module_list() as $module) {
$function = $module . '_hook_info_alter'; // hook_info_alter钩子
if (function_exists($function)) {
$function($hook_info);
}
}
return $hook_info;
}
自定义的钩子可以在hook_info中注册,也可以不注册。注册的好处是可以为钩子实现人员提供更详细的详细,另外一个目的是可以为钩子分组。例如,定义了很多admin有关的钩子,这些钩子函数我们想把它们单独放在一个PHP文件里面,而不用都挤在模块主文件。
module_implements()函数返回实现某个钩子的所有函数,它用module_list()遍历当前激活的所哟模块:
function module_implements($hook, $sort = FALSE, $reset = FALSE) {
$implementations = &$drupal_static_fast['implementations'];
if (!isset($implementations[$hook])) {
$hook_info = module_hook_info(); // 查询钩子信息
$implementations[$hook] = array();
$list = module_list(FALSE, FALSE, $sort);
foreach ($list as $module) {
// 注意这里额外载入了钩子分组文件
$include_file = isset($hook_info[$hook]['group']) && module_load_include('inc', $module, $module . '.' . $hook_info[$hook]['group']);
// Since module_hook() may needlessly try to load the include file again,
// function_exists() is used directly here.
if (function_exists($module . '_' . $hook)) {
$implementations[$hook][$module] = $include_file ? $hook_info[$hook]['group'] : FALSE;
}
}
// Allow modules to change the weight of specific implementations but avoid
// an infinite loop.
if ($hook != 'module_implements_alter') {
drupal_alter('module_implements', $implementations[$hook], $hook);
}
}
else {
foreach ($implementations[$hook] as $module => $group) {
// If this hook implementation is stored in a lazy-loaded file, so include
// that file first.
if ($group) {
// 注意这里额外载入了钩子分组文件
module_load_include('inc', $module, "$module.$group");
}
// It is possible that a module removed a hook implementation without the
// implementations cache being rebuilt yet, so we check whether the
// function exists on each request to avoid undefined function errors.
// Since module_hook() may needlessly try to load the include file again,
// function_exists() is used directly here.
if (!function_exists($module . '_' . $hook)) {
// Clear out the stale implementation from the cache and force a cache
// refresh to forget about no longer existing hook implementations.
unset($implementations[$hook][$module]);
$implementations['#write_cache'] = TRUE;
}
}
}
return array_keys($implementations[$hook]);
}
module_invoke_all()则调用所有实现某个钩子的所有函数,这是Drupal钩子系统的最外层接口:
function module_invoke_all($hook) {
$args = func_get_args();
// Remove $hook from the arguments.
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;
}
例如,我们要调用menu钩子,简单的调用module_invoke_all()就可以了:
$items = module_invoke_all('menu');
Drupal的钩子系统的更多相关文章
- Docker——基于Docker安装Drupal博客系统
Docker--基于Docker安装Drupal博客系统 向脚本文件追加内容 cat << EOF > build.sh #设置主机名 hostnamectl set-hostnam ...
- Drupal 7.23:函数drupal_alter()注释
/** * Passes alterable variables to specific hook_TYPE_alter() implementations. * * This dispatch fu ...
- drupal node机制理解
[1]根据结构的功能结构的不同,drupal划分为,node,user,comment等不同的结构,他们的结构是不同的.他们可以作为四个不同的抽象类,根据这个抽象类,分别有一套hook函数去控制实现的 ...
- Drupal theme_hook
模板语言和主题引擎 用Drupal的行话来说,主题就是一组负责你站点外观的文件.你可以从http://drupal.org/project/Themes下载第 3方主题,或者你可以自己动手创建一个主题 ...
- PHP钩子机制
什么是钩子 大家想必听过插件,wordpress插件特别多,这个就是用钩子机制实现的. 当代码在运行的过程中,我们预先在运行的几个特殊点里执行一些特殊方法:例如在运行方法(例如Blog::add的ad ...
- 高校应该使用 Drupal 的10大理由
使用 Drupal 已经成为全球顶尖高校中的一种潮流,它已经被全球数以百计的院校选择并应用,无论是哈佛.斯坦福.杜克.布朗.罗格斯.剑桥.耶鲁还是其它众多知名高校,都已经选择 Drupal 作为它们理 ...
- PHP之运用CI用钩子实现URL权限控制————————【Badboy】
<span style="background-color: rgb(247, 252, 255); font-family: Verdana, Arial, Helvetica, s ...
- 谈PHP中的钩子
钩子,英文为hooks.在程序中应用相当广泛,但是究竟什么是钩子呢?本人介绍一下目前本人对钩子的理解和相关心得. 假如有这么一段程序流: function fun(){ funA(); funB(); ...
- [Drupal]主题教程
drupal6和drupal7的主题开发有很大不同,本指南包含了这些不同 drupal7的默认主题是Bartik,6的是Garland drupal的主题系统是如何工作的 这部分内容主要讲述的是dru ...
随机推荐
- D - Matrix Multiplication ZOJ - 2316 规律题
Let us consider undirected graph G = which has N vertices and M edges. Incidence matrix of this grap ...
- [Atcoder Grand Contest 004] Tutorial
Link: AGC004 传送门 A: …… #include <bits/stdc++.h> using namespace std; long long a,b,c; int main ...
- HDOJ(HDU) 3949 XOR
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissio ...
- HDU 6035 Colorful Tree(补集思想+树形DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6035 [题目大意] 给出一颗树,一条路径的价值为其上点权的种类数,求路径总价值 [题解] 单独考虑 ...
- [NOIp2017提高组]小凯的疑惑
题目大意: 给你两个数a,b,保证a与b互质,求最大的x满足不能被表示成若干个a与b的和. 思路: 据说是小学奥数题. 考场上先写了个a*b的60分DP,然后打表发现答案就是(a-1)*(b-1)-1 ...
- canvas之arcTo
arc与arcTo,从名字都能看出来相似.arcTo也是画曲线的方法,而且他画出的曲线也是正圆的一段弧线.但他的参数和arc简直是不共戴天~ ctx.arcTo(x1,y1,x2,y2,radius) ...
- atomic与nonatomic的区别
原子性(atomic):某操作具备整体性,也就是说,系统其他部分无法观察到其中间步骤所生成的临时结果,而只能看到操作前与操作后的结果,那么就称改操作就是“原子的”(atomic),或者说,该操作具备“ ...
- python实现多播数据的发送和接收
在项目中,YS私有协议用到多播技术,在验证其安全特性时用到python去发送多播包,在此做个记录. 多播服务器用于向多播组发送多播数据包,其实现代码如下: #coding:utf-, import s ...
- 一劳永逸的搞定 flex 布局
一劳永逸的搞定 flex 布局 寻根溯源话布局 一切都始于这样一个问题:怎样通过 CSS 简单而优雅的实现水平.垂直同时居中.记得刚开始学习 CSS 的时候,看到 float 属性不由得感觉眼前一亮, ...
- Oracle 11gR2 RAC的两个bug
Oracle 11.2.0.2 bug还是不少的.很多库迁到Oracle 11.2.0.2后都遇到了问题.现在正在跟的两个Oracle 11.2.0.2上的问题:1.ORA-00600: inte ...