drpual教程.docx
- 文档编号:24243067
- 上传时间:2023-05-25
- 格式:DOCX
- 页数:23
- 大小:28.38KB
drpual教程.docx
《drpual教程.docx》由会员分享,可在线阅读,更多相关《drpual教程.docx(23页珍藏版)》请在冰豆网上搜索。
drpual教程
创建相应的文件
星期二,2009-07-2820:
08—g089h515r806
老葛的Drupal培训班
首先我们要做的是为模块起一个名字。
名字“annotate”看起来还是比较合适的—简洁而生动。
接着,我们需要找个地方来放置这个模块。
我们可以把这个模块放在核心模块所在的目录中去,不过这样的话,我们需要记住哪些是核心模块,哪些是我们的模块,这样一来,就增加了维护成本。
让我们把它放在目录sites/all/modules下面,以将其与核心模块区分开来。
如果sites/all/modules不存在,那么首先需要创建它。
接着在sites/all/modules下面在创建一个名为custom的目录,然后在sites/all/modules/custom下面创建一个名为annotate的目录。
这样就可以将你开发的自定义模块与你下载的第3方模块区分开了。
如果有一天,你需要将你的网站委托给另一个开发者,那么这一点还是很有帮助的,不过是否将它们区分开来,取决于你的决定。
我们创建的是一个子目录,而不是一个annotate.module文件,这是因为在我们的模块中,除了模块文件以外,我们还需要一些其它的文件。
比如我们需要一个README.txt文件,用来向其他用户解释我们的模块是做什么的,以及如何使用它,还有一个annotate.info文件用来向Drupal提供一些关于我们模块的信息。
准备好了吗?
现在让我们正式开始。
我们的annotate.info文件内容如下:
;$Id$
name=Annotate
description=Allowsuserstoannotatenodes.
core=6.x
package=ProDrupalDevelopment
这个文件的格式非常简单,在这里一个键对应一个值。
我们从版本管理系统(CVS)的标识标签开始。
如果我们想和其他用户分享这一模块,通过将它提交到Drupal的第3方模块资源库中,这个值将会被CVS自动替换。
接着,我们为Drupal提供了一个名称和一个描述,用来显示在网站的模块管理部分。
我们明确的定义了我们的模块所兼容的Drupal主版本;在这里,就是版本6.x。
Drupal6以及以后的版本将不允许启用不兼容的模块。
模块是按组来显示的,而组的划分是由包(package)决定的;这样,如果我们有3个不同的模块,它们都有package=ProDrupalDevelopment,那么它们将被放在同一组中。
除了前面所列的这些,我们还可以指定一些可选的值。
我们再看一个例子,下面的这个模块,它需要PHP5.2,依赖于论坛和分类模块:
;$Id$
name=Forumconfusion
description=Randomlyreassignsrepliestodifferentdiscussionthreads.
core=6.x
dependencies[]=forum
dependencies[]=taxonomy
package="EvilBob'sForumBonusPak"
php=5.2
注意你可能会想,为什么我们需要一个单独的.info文件呢?
为什么不在我们的主模块中写一个函数来返回这些元数据呢?
这是因为在加载模块管理页面时,它将不得不加载并解析每一个模块,不管有没有启用,这比平时需要更多的内存并且可能超出分配给PHP的内存上限。
通过使用.info文件,可以更快的加载信息并使用最小的内存。
现在我们准备好创建一个实际的模块了。
在你的sites/all/modules/custom/annotate子目录下面创建一个名为annotate.module的文件。
在文件的开始出使用PHP的开始标签和一个CVS标识标签,并紧跟一个注释:
php
//$Id$
/**
*@file
*Letsusersaddprivateannotationstonodes.
*
*Addsatextfieldwhenanodeisdisplayed
*sothatauthenticatedusersmaymakenotes.
*/
首先,让我们看一下注释的风格。
我们从/**开始,在接下来的每一行中缩进一格并以*开头,最后以*/结束。
令牌@file意味着在接下来的一行是一个描述,给出这个文件的用途。
模块api.module,Drupal的自动化文档提取器和格式器,可以使用这一行描述来找出这个文件的用途。
空了一行以后,我们为可能检查(并且改进)我们代码的程序员提供了一个更长的描述。
注意,我们在这里有意的不使用结束标签?
>;这对于PHP来说是可选的,如果包含了它,就可能导致文件的尾部空格问题(参看http:
//drupal.org/node/545)。
实现一个钩子
星期二,2009-07-2820:
09—g089h515r806
老葛的Drupal培训班
回想一下,我们曾经说过Drupal是建立在钩子系统之上,有时候钩子也被称为回调。
在执行的过程中,Drupal询问模块看它们是不是想要做些事情。
举例来说,为了判定哪一个模块负责当前的请求,它向所有的模块询问是否提供了相应的路径。
通过创建一个所有模块的列表,并且调用每个模块中名为:
模块名+_menu的函数,来实现这一点。
当它遇到我们的annotate模块时(应该会比较早的遇到,因为模块列表默认是按照字母顺序排列的),它调用函数annotate_menu(),后者返回一个包含菜单项的数组。
每一项(我们这里只有一项)都以路径为键,在这里就是admin/settings/annotate。
菜单项的值是一个数组,里面包含的键和值是用来描述在该路径被请求时Drupal要做什么的。
这方面的更多详细,可参看第4章
,该章讲述了Drupal的菜单/回调系统。
下面给我们模块添加点内容:
/**
*Implementationofhook_menu().
*/
functionannotate_menu(){
$items['admin/settings/annotate']=array(
'title'=>'Annotationsettings',
'description'=>'Changehowannotationsbehave.',
'pagecallback'=>'drupal_get_form',
'pagearguments'=>array('annotate_admin_settings'),
'accessarguments'=>array('administersiteconfiguration'),
'type'=>MENU_NORMAL_ITEM,
'file'=>'annotate.admin.inc',
);
return$items;
}
此时不要过于关注这里的具体细节。
这段代码说,“当用户访问页面annotate_admin_settings,在文件annotate.admin.inc中查找描述该表单的函数。
只有具有管理站点配置权限的用户才有权查看这个菜单。
”当需要显示表单时,Drupal就会让我们提供一个表单定义(一会儿就对这一点详细讲解)。
当Drupal完成了向所有的模块询问它们的菜单项时,它就为正被请求的路径找到一个菜单,根据这个菜单就会找到一个要被调用的函数。
注意如果你对钩子机制感兴趣的话,参看文件includes/module.inc里面的函数module_invoke_all()。
现在你应该清楚我们为什么把它叫作hook_menu()或者菜单钩子了。
可以通过在钩子的名字前加上你的模块名来创建Drupal钩子。
提示Drupal的钩子几乎允许你修改这个软件的任何方面。
你可以在Drupal的API文档站点(http:
//api.drupal.org)上,找到Drupal钩子的完整列表和它们的使用说明。
添加特定于模块的设置
(1)
星期二,2009-07-2820:
11—g089h515r806
Drupal有多种不同的节点类型(在用户界面称之为内容类型),比如Story和Page。
我们想将注释的使用限定在特定的一些节点类型上。
为了实现这一点,我们需要创建一个页面,在里面告诉我们的模块我们想注释哪些节点类型。
在该页面,我们将呈现一组复选框,每一个复选框就对应一个已有的内容类型。
这样终端用户就可以通过选中或者取消选中复选框(如图2-1所示),就可以决定哪些内容类型可被注释。
这样的页面就是一个管理页面,只有在需要的时候才加载和解析合成该页面的代码。
因此,我们把代码放在了一个单独的文件中,而不是放在我们的annotate.module文件里,而对于每个web请求,都会加载和运行annotate.module文件。
由于我们告诉了Drupal,在文件annotate.admin.inc中查找我们的设置表单,所以创建文件sites/all/modules/custom/annotate/annotate.admin.inc,并向里面添加以下代码:
php
//$Id$
/**
*@file
*Administrationpagecallbacksfortheannotatemodule.
*/
/**
*Formbuilder.Configureannotations.
*
*@ingroupforms
*@seesystem_settings_form().
*/
functionannotate_admin_settings(){
//Getanarrayofnodetypeswithinternalnamesaskeysand
//"friendlynames"asvalues.E.g.,
//array('page'=>'Page','story'=>'Story')
$options=node_get_types('names');
$form['annotate_node_types']=array(
'#type'=>'checkboxes',
'#title'=>t('Usersmayannotatethesecontenttypes'),
'#options'=>$options,
'#default_value'=>variable_get('annotate_node_types',array('page')),
'#description'=>t('Atextfieldwillbeavailableonthesecontenttypes tomakeuser-specificnotes.'),
);
returnsystem_settings_form($form);
}
添加特定于模块的设置
(2)
星期二,2009-07-2820:
13—g089h515r806
在Drupal中,表单被表示为一个嵌套的树状结构;也就是说,一个数组的数组。
这个结构向Drupal的表单呈现引擎(renderingengine)描述了表单是如何表示的。
为了可读性,我们将数组中的每个元素单独成行。
每一个表单属性都以”#”开头,并作为数组的键。
我们首先声明了表单元素的类型为checkboxes,这意味着通过使用一个带键的数组来构建多个复选框。
我们在变量$options中已经得到了带键的数组。
我们将选项(options)赋值为node_get_types('names'),该函数方便的返回了一个键值数组,里面包含了当前Drupal中可用的节点类型。
它的输出看起来像这个样子:
'page'=>'Page','story'=>'Story'
数组的键就是节点类型在Drupal中的内部名字,而把可读性的名字(显示给用户的)放到了右边。
如果你的Drupal中有一个名为“SavoryRecipe”的节点类型,那么数组看起来应该这样:
'page'=>'Page','savory_recipe'=>'SavoryRecipe','story'=>'Story'
因此,在我们的web表单中,为节点类型page和story生成了相应的复选框。
我们通过定义属性#title的值,为表单元素设置了一个标题。
注意显示给用户的任何文本(比如我们表单字段的#title和#description属性),都放在了t()函数中,这个函数在Drupal中是用来翻译字符串的。
通过把所有文本经过一个字符串翻译函数的处理,那么将你的模块本地化为一个不同的语言将会非常简单。
我们没有在菜单项中使用该函数,这是因为菜单项会被自动翻译。
下一个指示,#default_value,将是这个表单元素的默认值。
由于checkboxes是一个多值的表单元素(也就是说,存在多于一个的复选框),所以#default_value的值将会是一个数组。
老葛的Drupal培训班
添加特定于模块的设置(3)
星期二,2009-07-2820:
14—g089h515r806
老葛的Drupal培训班
这里值得讨论一下#default_value的值:
variable_get('annotate_nodetypes',array('page'))
Drupal允许程序员使用特定的一对函数:
varialble_get()和varialble_set()来存储和取回任意值。
值将被存储到数据库表variables中,并且在处理一个请求的任意时候都是可用的。
由于在处理每个请求时都会取回这些值,所以这种方法不能用来存储大量的数据。
对于配置属性这样简单数值的存储,它却是一个非常方便的系统。
注意我们传递给varialble_get()的是一个描述我们的值的键(所以我们可以取回它),和一个默认值。
在这种情况下,默认值是一个数组,里面包含了允许注释的节点类型。
在默认情况下,我们允许对节点类型page进行注释。
提示当使用system_settings_form()时,表单元素(在这里就是annotate_node_types)的名字必须匹配variable_get()中所用的键。
最后我们提供一个描述,用来告诉站点管理员关于这个字段的一些更细节的信息。
保存你刚创建的文件,然后导航到“管理➤站点构建➤模块”。
在标题为proDrupalDevelopment的组中,在模块列表的最后,你应该能够看到你的模块了(如果没有的话,那么仔细的检查你的annotate.info和annotate.module文件;并确保它们位于sites/all/modules/custom目录中)。
继续前进,启用你的新模块。
现在导航到“管理➤设置➤注释”,我们将看到annotate.module所显示的配置表单了(如图2-1所示)。
图2-1,annotate.module生成的配置表单。
仅用了几行代码,我们就为我们的模块提供了一个可用的配置表单,它将自动的保存和记住我们的设置!
好的,尽管代码中的一行有点太长了,但是没有关系,你现在应该能够感受到撬动Drupal的力量了。
添加数据输入表单
(1)
星期二,2009-07-2820:
17—g089h515r806
为了让用户可以为一个web页面输入笔记,我们需要为它提供一个地方,专门用来输入笔记。
下面我们在annotate.module中为笔记添加一个表单:
(译者注:
这里的笔记就是注释的意思)
/**
*Implementationofhook_nodeapi().
*/
functionannotate_nodeapi(&$node,$op,$teaser,$page){//$node调用节点,这个变量确定传过来的是一个节点,也就相当于一个内容页面,从而确定是在内容页面中添加的笔记而不是其他地方。
$op保存的是操作,也就是保存的是增、删、改、查、保存等等的动作。
global$user;
switch($op){
//The'view'operationmeansthenodeisabouttobedisplayed.
case'view':
//Abortiftheuserisananonymoususer(notloggedin)or
//ifthenodeisnotbeingdisplayedonapagebyitself
//(forexample,itcouldbeinanodelistingorsearchresult).
if($user->uid==0||!
$page){
break;
}
//Findoutwhichnodetypesweshouldannotate.
$types_to_annotate=variable_get('annotate_node_types',array('page'));
//Abortifthisnodeisnotoneofthetypesweshouldannotate.
if(!
in_array($node->type,$types_to_annotate)){
break;
}
//Addourformasacontentitem.
$node->content['annotation_form']=array(
'#value'=>drupal_get_form('annotate_entry_form',$node),
'#weight'=>10
);
break;
}
}
添加数据输入表单
(2)
星期二,2009-07-2820:
19—g089h515r806
这个看起来有点复杂,所以让我们详细的分析一下。
首先要注意的是,我们在这里实现了Drupal的另一个钩子。
这次是nodeapi钩子,在drupal对节点进行各种处理时将会调用该钩子,这样其它的模块(比如我们的)在处理继续往下以前可以修改节点。
我们通过变量$node将节点传递过来。
注意第一个参数前面的&,这意味着它实际上是对$node对象的一个引用,这点非常好,因为我们在这里对$node所做的任何修改都将被保存下来。
由于我们的目标是追加一个表单,所以我们非常高兴地看到我们可以修改节点。
我们仍然需要一些信息----在我们的代码被调用时在Drupal中将发生什么。
这些信息保存在了参数$op中,它可以是insert(节点正被创建),delete(节点正被删除),或者一个其它的值。
当前,我们只有当节点正准备显示出来时,才想对其进行修改。
在这种情况下,变量$op的值就是view。
我们在这里使用了switch控制语句,这样我们就可以非常容易的添加其它情况,并且能够方便的看到在每种情况下我们的模块将做什么。
接下来,我们快速的检查了一些我们不想显示注释字段的情况。
一种情况是$user对象的用户ID为0时,这意味着查看节点的用户此时没有登录(注意,在这里我们使用关键字global将$user对象包含了进来,这样我们就可以测试当前用户是否登录了)。
另一种情况是当参数$page不为TRUE时,我们想阻止表单的显示。
如果它为FALSE,这意味着,这个节点并不是单独显示的,而是显示在一个列表中,比如说一个搜索引擎的结果中,或者一个最近更新的节点列表中。
在这些情况下,我们不需要添加任何东西。
我们使用break语句来跳出switch语句从而阻止对页面的修改。
在我们为web页面添加注释表单以前,我们需要检查一下,将要进行显示的节点的类型是不是我们在设置页面所启用的类型中的一个,所以我们取回了在我们实现设置钩子时所保存的节点类型数组。
我们将它保存到了变量$types_to_annotate中去。
对于variable_get()中的第2个参数,我们在这里声明了一个默认数组,用于站点管理员还没有访问我们模块的设置页面来输入设置的情况。
下面要做的就是检查一下,我们所要处理的节点的类型是不是包含在$types_to_annotate中。
同样,如果节点类型不是我们想要注释的,我们将使用break语句来跳出switch语句。
老葛的Drupal培训班
添加数据输入表单(3)
星期二,2009-07-2820:
20—g089h515r806
我们最后要做的就是创建表单,并把它添加到$node对象中。
首先,我们需要定义一个表单,这样我们就有了要添加的东西。
我们将在annotate.module中的一个单独的函数中完成这件事,它唯一的责任就是定义表单:
/**
*Definetheformforenteringanannotation.
*/
functionannotate_entry_form($form_state,$node){
//Defineafieldset.
$form['annotate']=array(
'#type'=>'fieldset',
'#title'=>t('Annotations'),
);
//Defineatextareainsidethefieldset.
$form['annotate']['note']=a
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- drpual 教程