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 ...
随机推荐
- 有的系统区apk需要对其系统签名,才能正常使用。
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 向方案公司索要platform.x509.pem 和platform.pk8这两个文件. ...
- poj 1681(Gauss 消元)
Painter's Problem Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5875 Accepted: 2825 ...
- for循环、for-in、forEach、for-of四大循环
平时自己在写一些小栗子的时候,用到的基本上是for循环,因为在学专业课(C,C++,JAVA,...)的时候用的最多的就是for循环,不过for循环的效率也是比较高的. 但是for循环在写的时候,涉及 ...
- NHibernate之一级缓存(第十篇)
NHibernate的一级缓存,名词好像很牛B,很难.实际上就是ISession缓存.存储在ISession的运行周期内.而二级缓存则存储在ISessionFactory内. 一.ISession一级 ...
- C# base64编码的字符串与图片互转
protected string ImgToBase64String(string Imagefilename) { try { Bitmap bmp = new Bitmap(Imagefilena ...
- win7与Ubuntu 13.04双系统修改启动项顺序
在在win7下安装了Ubuntu 13.04后,在grub中,win7启动想是最后一个,为了把win7设置为默认启动项,需要更改grub设置.google了半天,发现更改/etc /default/g ...
- easyui 后台系统引入富文本编辑器的使用
1.首先,想在项目中引入相关的jar包 2.html页面中加入相关的引用 <!-- kindeditor --> <script type="text/javascript ...
- jenkins平台通过maven方式使用sonar报大量关于html/css/js的错误解决办法
1.如果项目只关注java的源代码扫描,可以在sonar上把检查html.css.js的插件卸载,让后重启sonar避免不需要检查的内容报错误
- Foreach控件使用
在SSIS中,Foreach控件可以循环处理选中的文件中的文件,例如sql文件,Excel文件等.下面就介绍一个比较经典的案例,将一个文件夹中包含的多个Excel文件循环导入至数据库中. 第一步:在数 ...
- OpenWRT DNS无法解析WAN连接的内网服务器域名
系统版本OpenWrt Chaos Calmer 15.05.1,网络连接为:WAN口连接内网10.x.x.x网段,WAN口设置为静态IP.设置L2TP接口,通过L2TP访问外网.问题出现于,所有外网 ...